Pregunta

Estoy intentando crear una clase con muchos parámetros, utilizando un patrón de constructor en lugar de constructores telescópicos. Estoy haciendo esto de la manera descrita por Java efectiva de Joshua Bloch, con un constructor privado en la clase Closing y una clase pública de constructor estático. La clase de constructor asegura que el objeto esté en un estado consistente antes de llamar a Build (), momento en el cual delega la construcción del objeto adjunto al constructor privado. De este modo

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);
        }

    }

}

Luego quiero agregar límites de tipo a algunas de las variables y, por lo tanto, necesito parametrizar la definición de clase. Quiero que los límites de la clase Foo sean los mismos que los de la clase Builder.

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);
        }

    }

}

Esto se compila bien, pero el compilador me permite hacer cosas que creo que deberían ser errores del compilador. P.ej

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

Aquí el argumento de las unidades no es Unit<Acceleration> pero Unit<Length>, pero todavía es aceptado por el compilador.

¿Qué estoy haciendo mal aquí? Quiero asegurarme de que los tipos de unidad coincidan correctamente.

¿Fue útil?

Solución

units debería regresar Builder<Q>, no un no generificado Builder.

Otros consejos

Aunque el punto de @Daniel es válido, al menos el error en su código se ve al menos. Por supuesto, tu definición de Quantity, Unit y METER es probablemente diferente del truco simplista que armé:

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();

El mensaje de error es:

The method units(Unit<Acceleration>) in the type Foo.Builder<Acceleration> is
not applicable for the arguments (Unit<Length>)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top