Шаблон Java Builder с общими границами типа
-
27-09-2019 - |
Вопрос
Я пытаюсь создать класс со многими параметрами, используя узор строителя, а не телескопированные конструкторы. Я делаю это на пути, описанным эффективным Java Jowaa Bloch, имея частную конструктор на обложенном классе, а также общедоступный класс статического строительства. Класс Builder гарантирует, что объект находится в последовательном состоянии до вызова сборки (), в результате которого он делегирует строительство окружающего объекта к частному конструктору. Таким образом
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);
}
}
}
Затем я хочу добавить границы типа к некоторым из переменных и, таким образом, необходимо параметризировать определение класса. Я хочу, чтобы прерывания класса Foo совпадают так же, как у класса 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);
}
}
}
Это компилируется нормально, но компилятор позволяет мне делать то, что я чувствую, должен быть ошибками компилятора. Например
public static final Foo.Builder<Acceleration> x_Body_AccelField =
new Foo.Builder<Acceleration>()
.units(SI.METER)
.build();
Здесь аргумент единиц не Unit<Acceleration>
но Unit<Length>
, Но он все еще принимается компилятором.
Что я здесь делаю не так? Я хочу обеспечить время с компиляцией, что типы единиц соответствуют правильно.
Решение
units
должен вернуться Builder<Q>
, не бесписан Builder
.
Другие советы
Хотя @ Daniel Point действительна, по-прежнему ошибка в вашем коде определяется по меньшей мере затмить. Конечно, ваше определение Quantity
, Unit
и METER
Вероятно, отличается от упрощенного взлома, которую я собрал вместе:
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();
Сообщение об ошибке:
The method units(Unit<Acceleration>) in the type Foo.Builder<Acceleration> is
not applicable for the arguments (Unit<Length>)