Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
class Parent<T extends Parent> {
public T fn1(String arg1) {
// TO DO SMTHNG W/ arg1 HERE ...
return (T)this;
}
}
class Descendant<T extends Descendant> extends Parent<Descendant> {
@Override
public T fn1(String arg1) {
return (T)super.fn1(arg1);
}
public T fn2(String arg2) {
// TO DO SMTHNG W/ arg2 HERE ...
return (T)this;
}
}
// ... USING:
Descendant sc = new Descendant();
sc.fn1("1").fn2("2");
public T fn1(String arg1) {
return (T)super.fn1(arg1);
}
Так там копипаста и не нужна если дженерики чуть аккуратнее написать.
class B1<T extends B1<T>> {
public T fn1(String v) {
return (T) this;
}
}
class B2<T extends B2<T>> extends B1<T> {
public T fn2(String v) {
return (T) this;
}
}
class B3<T extends B3<T>> extends B2<T> {
public T fn3(String v) {
return (T) this;
}
}
class FB1 extends B1<FB1> {}
class FB2 extends B2<FB2> {}
class FB3 extends B3<FB3> {}new FB3().fn1("1").fn2("2").fn3("3")смысл в том, чтобы передавать дочерний билдер в функции, которые хотят родительский
И почему не спасло <? extends BaseBuilder>— тогда не получится нормально использовать цепочу. функция установки поля вернет BaseBuilder и на этом все закончится
class AddressAttacher implements DtoBuilerChain {
@override
void doChainStep(DtoBuilder builder) {
bulder.fromAddress(someAddressFrom).toAddress(someAddressTo);
}
}
DtoBuile builder = Dto.builder();
listOfDtoBuilerChain.forEach( chain -> chain.doChainStep(builder));
DtoObject obj = builder.build();
смысл в том, чтобы передавать дочерний билдер в функции, которые хотят родительский. скрестите билдер и chain of responsibility и там это потребуется.
про создание на каждый builder — зависит от ситуации
в 3м вариаенте надо объяснить прользователю, почему такой кривой объект dto, потому что с его точки зрения это одно поле ничем не хуже других. за что его вынесли на верхний уровень — пользователю не понятно
он не иммутабл
члены цепочки обмениваются недостроенным объектом. что тоже не очень хорошо
В чем смысл билдера, если ваш класс и так содержит сеттеры для полей?— для наглядности. можно было их и убрать в принципе.
Но, по-моему, корень в
ашей проблемы в использовании наследования (которое, из моего скромного опыта, является верным решением менее чем в 1% случаев). Может быть, в вашем случае можно применить композицию вместо наследования?
если исходные объекты унаследованы
это придется делать в каждом методе, который возвращает билдер — очень некрасиво
@SuppressWarnings("unchecked")
RetBuilder self() {
return (RetBuilder) this;
}
RetBuilder foo(int x) {
nested.setFoo(x);
return self();
}
builder.foo(1).bar(2)object.setFoo(1);
object.setBar(2);
Правильный полиморфный билдер на Java