我有以下实现抽象构建器的代码(如有效的 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
}
我想做的是 - 从 A
类中的 ret()
方法,我想构造不了解父类型的不可变对象(immutable对象) - 所以在我的示例是具有新内部字符串的新类 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;
}
}
}
最佳答案
你需要在A
中提供一个抽象方法来构造一个合适的Builder
实例:
abstract Builder<A> toBuilder();
然后在具体的子类中实现它,并调用:
return toBuilder().withString(s).build();
关于java - 构造不可变对象(immutable对象)的抽象生成器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53815128/