У меня есть следующий код, реализующий абстрактный конструктор (как в эффективной книге Java):
interface I {
I ret();
}
abstract class A implements I {
private String s = "";
A(Builder b) {
s = b.s;
}
@Override
public I ret() {
String s = "some new string from calc.";
//HERE I NEED TO CONSTRUCT class B
//THIS IS PROBLEMATIC LINE BELOW <<<<--------------------------------------
return new Builder<>().withString(s).build();
}
static abstract class Builder<T extends Builder<T>> {
String s = "";
T withString(String s) {
this.s = s;
return self();
}
protected abstract A build();
//simulated self-type idiom
protected abstract T self();
}
}
class B extends A {
private B(A.Builder b) {
super(b);
}
static class Builder extends A.Builder<Builder> {
@Override
protected B build() {
return new B(this);
}
@Override
protected Builder self() {
return this;
}
}
}
, и это небольшой вариант использования
public static void main(String[] args) {
I b = new B.Builder().withString("bclass").build();
I b2 = b.ret(); //<---- this one should construct new immutable B
}
Что я хочу сделать, это -из ret()
метода в классе A
я хотел бы построить неизменный объект, который не знает родительский тип - поэтому в моем примере это будет новый класс B
, который имеет новую внутреннюю строку.
Проблема в том, что класс A
не знает о классе B
, поскольку B
является его родителем.
Возможно ли что-то подобное, не прибегая к дженерикам?
Если я использую изменяемыйкласс, это будет так просто, как this.s = newS;
.
ОБНОВЛЕНИЕ
abstract class A implements I {
private String s = "";
A(Builder b) {
s = b.s;
}
@Override
public I ret() {
String s = "SOME NEW STING FROM CALCULATION";
return builder().withString(s).build();
}
abstract Builder<?> builder();
static abstract class Builder<T extends Builder<T>> {
String s = "";
T withString(String s) {
this.s = s;
return self();
}
protected abstract A build();
//simulated self-type idiom
protected abstract T self();
}
}
class B extends A {
B(A.Builder b) {
super(b);
}
@Override
Builder builder() {
return new Builder();
}
static class Builder extends A.Builder<Builder> {
@Override
protected B build() {
return new B(this);
}
@Override
protected Builder self() {
return this;
}
}
}