Разработчик Java шаблон с Универсальными границами типа

Я пытаюсь создать класс со многими параметрами, с помощью шаблона Разработчика вместо того, чтобы сложиться конструкторов. Я делаю это в пути, описанном Эффективным Java Joshua Bloch, имея частного конструктора на классе включения и общедоступном статическом классе Разработчика. Класс Разработчика гарантирует, что объект находится в согласованном состоянии перед называнием сборки (), в которой точке это делегирует конструкцию вложенного объекта к частному конструктору. Таким образом

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 совпали с границей класса Разработчика.

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>, но это все еще принято компилятором.

Что я делаю неправильно здесь? Я хочу удостовериться во время компиляции, чтобы типы единицы совпали правильно.

5
задан I82Much 17 May 2010 в 22:23
поделиться

2 ответа

units должен возвращать Builder, а не негенерированный Builder.

7
ответ дан 14 December 2019 в 08:44
поделиться

Хотя замечание @Daniel справедливо, все же ошибка в вашем коде замечена, по крайней мере, Eclipse. Конечно, ваше определение Количество, Единица и МЕТР, вероятно, отличается от упрощенного хака, который я собрал вместе:

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>)
0
ответ дан 14 December 2019 в 08:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: