我想通过继承来实现构建器模式。所以我有以下 4 个类:一个抽象类(ClassA)、ClassB、ClassC。 TestTest 类用于查看这一切是如何工作的:
public abstract class ClassA {
private String aString;
public String getaString() {
return aString;
}
public abstract class ClassABuilder<T extends ClassABuilder>{
public T setaString(String str) {
ClassA.this.aString = str;
return (T)this;
}
public abstract ClassA build();
}
}
public class ClassB extends ClassA{
private String bString;
public String getbString() {
return bString;
}
public class ClassBBuilder<T extends ClassBBuilder> extends ClassA.ClassABuilder<T>{
public T setbString(String str) {
ClassB.this.bString = str;
return (T)this;
}
@Override
public ClassB build(){
return ClassB.this;
}
}
}
public class ClassC extends ClassB{
private String cString;
public String getcString() {
return cString;
}
public static ClassCBuilder<ClassCBuilder> newBuilder(){
return new ClassC().new ClassCBuilder();
}
public class ClassCBuilder<T extends ClassCBuilder> extends ClassB.ClassBBuilder<T>{
public T setcString(String str) {
ClassC.this.cString = str;
return (T)this;
}
@Override
public ClassC build(){
return ClassC.this;
}
}
}
public class TestTest {
public static void main(String[] args) {
// TODO code application logic here
ClassC C=ClassC.newBuilder()
.setaString(null)
.setbString(null)
.setcString(null) //LINE XXX
.build();
}
}
问题是,在 LINE XXX 的 TestTest 中,我找不到符号“setcString”。我做错了什么?
最佳答案
让我们沿着层次结构追踪它:
首先考虑这个签名:
class ClassABuilder<T extends ClassABuilder>
当您调用setaString(null)
时返回的T
将是一个扩展 ClassABuilder
的对象。编译器知道这是一个 ClassBBuilder
这样您就可以调用 setbString(null)
.
但是,由于定义规定 T
需要扩展 raw ClassBBuilder
仅关于 ClassBBuilder
的任何信息的泛型类型将会丢失。因此编译器只知道 T
是 ClassBBuilder
但并不是说它实际上是 ClassCBuilder
延伸ClassBBuilder<ClassCBuilder>
因此不知道 setcString()
关于返回的类型。
正如已经提到的,使用T extends ClassABuilder<T>
将解决这个问题,因为现在编译器知道还有另一个泛型类型要沿着层次结构传递。
newBuilder()
那么必须看起来像这样:
public static ClassCBuilder<?> newBuilder(){
//you have too create a raw type here so you'll have to ignore/suppress/live with the warning
return (new ClassC().new ClassCBuilder());
}
关于Java:构建器模式、继承和泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42977031/