Pergunta

Estou tentando criar uma classe com muitos parâmetros, usando um padrão Builder em vez de construtores telescópicos.Estou fazendo isso da maneira descrita por Effective Java de Joshua Bloch, tendo um construtor privado na classe envolvente e uma classe Builder estática pública.A classe Builder garante que o objeto esteja em um estado consistente antes de chamar build(), momento em que delega a construção do objeto envolvente ao construtor privado.Por isso

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

    }

}

Quero então adicionar limites de tipo a algumas das variáveis ​​e, portanto, preciso parametrizar a definição da classe.Quero que os limites da classe Foo sejam iguais aos da classe 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);
        }

    }

}

Isso compila bem, mas o compilador está me permitindo fazer coisas que considero que deveriam ser erros do compilador.Por exemplo.

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

Aqui o argumento das unidades não é Unit<Acceleration> mas Unit<Length>, mas ainda é aceito pelo compilador.

O que estou fazendo de errado aqui?Quero garantir, em tempo de compilação, que os tipos de unidade correspondam corretamente.

Foi útil?

Solução

units deveria retornar Builder<Q>, não um não gerado Builder.

Outras dicas

Embora o argumento de @Daniel seja válido, o erro no seu código ainda é detectado pelo Eclipse, pelo menos.Claro, sua definição de Quantity, Unit e METER provavelmente é diferente do hack simplista que criei:

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

A mensagem de erro é:

The method units(Unit<Acceleration>) in the type Foo.Builder<Acceleration> is
not applicable for the arguments (Unit<Length>)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top