问题描述
我想通过继承实现Builder模式。因此,我有以下4类:一个抽象类(ClassA),ClassB,ClassC。 TestTest类用于查看所有工作原理:
I want to implement Builder Pattern with inheritance. So I have 4 following classes: one abstract class (ClassA), ClassB, ClassC. TestTest class is used to see how all this works:
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();
}
}
问题是在XXX线的TestTest,我得到了找不到符号 setcString。我该怎么办?
The problem is that at TestTest at LINE XXX I get can't find symbol "setcString". What do I do wrong?
推荐答案
让我们沿着层次结构进行跟踪:
Let's track it down along the hierarchy:
首先考虑此签名:
class ClassABuilder<T extends ClassABuilder>
调用 setaString(null)
时返回的 T
将是扩展 ClassABuilder
的对象。编译器知道这是 ClassBBuilder
,因此将允许您调用 setbString(null)
。
When you call setaString(null)
the returned T
will be an object that extends ClassABuilder
. The compiler knows that this is a ClassBBuilder
and thus will allow you to call setbString(null)
.
但是,由于定义指出 T
需要扩展 raw ClassBBuilder
只会丢失有关 ClassBBuilder
泛型类型的任何信息。因此,编译器仅知道 T
是 ClassBBuilder
,而不是实际上是 ClassCBuilder
扩展了 ClassBBuilder< ClassCBuilder>
,因此不知道 setcString()
However, since the definition states T
is required to extend a raw ClassBBuilder
only any information on ClassBBuilder
's generic types will be lost. Thus the compiler only knows that T
is a ClassBBuilder
but not that it's actually a ClassCBuilder
which extends ClassBBuilder<ClassCBuilder>
and hence doesn't know about setcString()
on the returned type.
如前所述,使用 T扩展ClassABuilder< T>
可以解决此问题。编译器知道还有另一种通用类型要沿层次结构传递。
As has already been mentioned, using T extends ClassABuilder<T>
will fix that since now the compiler knows there's another generic type to be passed down the hierarchy.
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:构建器模式,继承和泛型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!