(对不起双关语)
假设有人想要定义一个通用构建器,如下所示:
public abstract class GenericBuilder<T extends Product> {
int x;
int y;
<K extends GenericBuilder<T>> K setX(int x) {
this.x = x;
return (K)this;
}
<K extends GenericBuilder<T>> K setY(int y) {
this.y = y;
return (K) this;
}
abstract T build();
}
abstract class Product {
int x;
int y;
}
class ConcreteProduct extends Product {
int z;
}
class ConcreteBuilder extends GenericBuilder<ConcreteProduct>{
int z;
<K extends GenericBuilder<ConcreteProduct>> K setZ(int z) {
this.z = z;
return (K) this;
}
@Override
ConcreteProduct build() {
ConcreteProduct cp = new ConcreteProduct();
cp.x = x;
cp.y = y;
cp.z = z;
return cp;
}
public static void main(String[] args) {
new ConcreteBuilder().setX(1).setY(2).setZ(3);
}
}
调用ConcreteBuilder.setZ()时,它在编译期间失败。
为什么?是否应该擦除?或者,仿制药不包含有关其通用参数的信息?
修改
任何想法如何避免在第二个通用参数中使用:
public class ConcreteBuilder extends GenericBuilder<ConcreteProduct, ConcreteBuilder>
即。 &lt; ...,ConcreteBuilder&gt ;,这似乎有点笨拙?我想这不可能。是否有其他语言(C#可能?)允许这样做?
答案 0 :(得分:2)
以这种方式破解您的代码,您将了解您的班级GenericBuilder<ConcreteProduct>
没有定义任何setZ()方法。
GenericBuilder<ConcreteProduct> setY = new ConcreteBuilder().setX(1).setY(2);
setY.setZ(3);
答案 1 :(得分:2)
在GenericBuilder
您的函数中,如果您未指定函数的类型参数,则返回GenericBuilder
。在您的主要功能中,对setX
的调用会返回GenericBuilder
,并且您将丢失实际使用ConcreteBuilder
的信息。要成功进行调用,您必须为setter指定通用参数:
new ConcreteBuilder().<ConcreteBuilder>setX(1).<ConcreteBuilder>setY(2).setZ(3);
您可以向GenericBuilder
添加第二个类型参数:
public abstract class GenericBuilder<T extends Product, K extends GenericBuilder<T, K>> {
int x;
int y;
K setX(int x) {
this.x = x;
return (K)this;
}
K setY(int y) {
this.y = y;
return (K) this;
}
abstract T build();
}
并将ConcreteBuilder
更改为:
public class ConcreteBuilder extends GenericBuilder<ConcreteProduct, ConcreteBuilder> {
int z;
ConcreteBuilder setZ(int z) {
this.z = z;
return this;
}
@Override
public ConcreteProduct build() {
ConcreteProduct cp = new ConcreteProduct();
cp.x = x;
cp.y = y;
cp.z = z;
return cp;
}
public static void main(String[] args) {
new ConcreteBuilder().setX(1).setY(2).setZ(3);
}
}