在Java中我有一个抽象基类,比方说WrapX
,它包含一个类型的属性,比如X
(想想装饰者DP)。此类提供了一种在封装的X
上调用特定方法的方法:
public abstract class WrapX{
protected X instance;
public WrapX(X x){
this.instance = x;
}
public void foo(){
instance.foo();
}
}
public class X {
public void foo(){
System.out.println("foo");
}
}
然后有一个名为Y
的类,它从X
延伸并提供了另一种方法:
public class Y extends X {
public void bar(){
System.out.println("bar");
}
}
然后我自然创建了WrapY
,可以用作Y
类型的装饰类型:
public class WrapY extends WrapX{
...
public void bar(){
instance.bar();
}
}
所以这就是问题所在。 WrapY
已从其父instance
继承了X
类型的WrapX
属性。就Eclipse而言,instance
的类型为X
,因此会抱怨它不包含方法.bar()
。
当然很公平,但是在这个子类中我们可以隐式地将instance
强制转换为instance
Y
(初始类型X
的有效子类)...不需要乱丢代码或变量阴影的显式强制转换?
如果我在构造函数中有这个:
public WrapY(Y y){
this.instance = y;
}
Eclipse仍然抱怨.bar()
不是X
类型的方法,因为我猜它无法推断在构造WrapY(Y y)
实例之前将使用WrapY
:
public void bar(){
instance.bar(); // ERROR
}
以下是我目前的方法,其中充斥着演员阵容:
public WrapY(Y y){
(Y)instance = y;
}
public void bar(){
((Y)instance).bar();
}
我之前没有遇到过这种特殊类型的架构问题,请在“基于装饰器的继承 - 类型 - 投射”(!)下进行归档...请告诉我如何对此进行建模以更好的方式。
另一个问题是,如果将来某人扩展WrapY
,他们的类继承的实例类型将是X
的自然(未发布)类型,当他们可能合理地认为它应该是输入Y
。
由于
答案 0 :(得分:2)
您可以使您的Wrap类具有通用性,例如:
public abstract class Wrap<T extends X>{
protected T instance;
public Wrap(T x){
this.instance = x;
}
public void foo(){
instance.foo();
}
}
public final class WrapY extends Wrap<Y> {
public WrapY(Y y) {
super(y);
}
public void bar(){
instance.bar();
}
}
然后,对于WrapY
的实例,instance
将是Y
。
更新: 如果你想继承WrapY(并解决最后一个包装类型是最合适的问题),请执行以下操作:
public class WrapY<U extends Y> extends Wrap<U> {
public WrapY(U y) {
super(y);
}
public void bar(){
instance.bar();
}
}