Я выполняю рефакторинг некоторого кода в шаблоне компоновщика и сталкиваюсь с проблемой при создании подкласса компоновщика для дочернего класса.
Когда у меня есть подкласс построителя, и я пытаюсь связать метод в родительском объекте, он возвращает родительский построитель, поэтому мой экземпляр больше не имеет доступа к методам дочернего класса.
public class App {
public static void main(String[] args) {
Parent p;
p = new App().new ChildBuilder()
.withName("Test")
.withNickName("Test1")
.build();// Doesn't Compile
p = new App().new ChildBuilder()
.withNickName("Test1")
.withName("Test")
.build();
}
class Parent {
public Parent(ParentBuilder builder) {}
}
class Child extends Parent {
public Child(ChildBuilder builder) { super(builder); }
}
class ParentBuilder {
private String name;
public ParentBuilder() {}
public Parent build() { return new Parent(this); }
public ParentBuilder withName(String name) {
this.name = name;
return this;
}
}
class ChildBuilder extends ParentBuilder {
private String nickName;
public ChildBuilder withNickName(String nickName) {
this.nickName = nickName;
return this;
}
}
}
Вторая строка в методе main не будет компилироваться, поскольку withName("Test")
находится в классе ParentBuilder и возвращает ParentBuilder.Переупорядочение цепочек для вызова всех методов ChildBuilder сначала решает проблему, но это звучит как ужасный опыт для людей, использующих мой API (включая меня).
Если я добавлю переопределение в ребенка, я смогу заставить его работать через ковариацию:
@Override
public ChildBuilder withName(String name) {
super.withName(name);
return this;
}
Но это много стандартного кода, который я бы предпочел не поддерживать (у каждого родительского компоновщика может быть несколько подклассов, поэтому мне нужно было бы переписать эти методы в каждом подклассе для каждого метода вродительский класс).
Есть ли способ сделать то, что я пытаюсь сделать без переопределений?Может ли Java "вывести" ковариантные методы у детей?
Я также обеспокоен тем, что эта проблема свидетельствует о том, что я неправильно проектирую строителей.