Frage

Ich versuche, eine Klasse mit vielen Parametern zu erstellen, wobei ich eher ein Builder -Muster als Teleskop -Konstruktoren verwende. Ich mache dies so, wie es von Joshua Blochs effektivem Java beschrieben wird, der private Konstruktor in der beigefügten Klasse und eine öffentliche statische Erbauerklasse hat. Die Builder -Klasse stellt sicher, dass sich das Objekt in einem konsistenten Zustand befindet, bevor er Build () aufruft (). Zu diesem Zeitpunkt delegiert es die Konstruktion des umschließenden Objekts an den privaten Konstruktor. Daher

public class Foo {

    // Many variables

    private Foo(Builder b) {
        // Use all of b's variables to initialize self
    }

    public static final class Builder {

        public Builder(/* required variables */) {

        }

        public Builder var1(Var var) {
            // set it
            return this;
        }

        public Foo build() {
            return new Foo(this);
        }

    }

}

Ich möchte dann einige der Variablen Typengrenzen hinzufügen und daher die Klassendefinition parametrisieren. Ich möchte, dass die Grenzen der FOO -Klasse die gleichen wie die der Builder -Klasse sind.

public class Foo<Q extends Quantity> {

    private final Unit<Q> units;
    // Many variables

    private Foo(Builder<Q> b) {
        // Use all of b's variables to initialize self
    }

    public static final class Builder<Q extends Quantity> {
        private Unit<Q> units;

        public Builder(/* required variables */) {

        }

        public Builder units(Unit<Q> units) {
            this.units = units;
            return this;
        }

        public Foo build() {
            return new Foo<Q>(this);
        }

    }

}

Dies kompiliert es gut, aber der Compiler erlaubt mir, Dinge zu tun, die ich für Compiler -Fehler tun sollte. Z.B

public static final Foo.Builder<Acceleration> x_Body_AccelField =
        new Foo.Builder<Acceleration>()
        .units(SI.METER)
        .build();

Hier ist das Argument der Einheiten nicht Unit<Acceleration> aber Unit<Length>, aber es wird immer noch vom Compiler akzeptiert.

Was mache ich hier falsch? Ich möchte bei der Kompilierung der Kompilierzeit sicherstellen, dass die Einheitstypen korrekt übereinstimmen.

War es hilfreich?

Lösung

units sollte zurückkehren Builder<Q>, kein nicht generifizierter Builder.

Andere Tipps

Obwohl der Punkt von @Daniel gültig ist, wird der Fehler in Ihrem Code zumindest von Eclipse entdeckt. Natürlich Ihre Definition von Quantity, Unit und METER unterscheidet sich wahrscheinlich von dem simplen Hack, den ich zusammengestellt habe:

interface Quantity {
}
class Acceleration implements Quantity {
}
class Length implements Quantity {
}
public class Unit<Q extends Quantity> {
    public static final Unit<Length> METER = new Unit<Length>();
}

public static final Foo.Builder<Acceleration> x_Body_AccelField =
    new Foo.Builder<Acceleration>()
    .units(Unit.METER) // here the compiler complains
    .build();

Die Fehlermeldung lautet:

The method units(Unit<Acceleration>) in the type Foo.Builder<Acceleration> is
not applicable for the arguments (Unit<Length>)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top