我有一些课程X
,其中包含字段A
。它是一个final结构域,在构造函数中初始化。现在我有一个派生类Y
,其中此字段必须始终是B
的实例,这是一个派生自A
的类。问题是,类Y
需要调用仅在B类上可用的数字特定方法,而不是在其祖先A
上。
我看到了几个解决方案:
A
类型的字段,继承自X
,并在类Y
内,将A
投射到B
。这使我的代码充满讨厌的类型转换。B
类型的其他字段。现在没有类型转换,但我们有两个略有不同类型的字段,必须始终保持相同的值 - 也感觉不太好。B
提供的所有方法也添加到A
,抛出NotImplementedException
。这增加了一些奇怪的方法,这些方法在那个课程中明显没有意义。哪种方式最适合处理这个领域?或者其他一些,更好的存在?我认为这不是特定于语言的,但我必须在Java中使用。
答案 0 :(得分:5)
X类型应该是泛型类型:
public class X<T extends A> {
protected T a;
public X(T a) {
this.a = a;
}
}
public clas Y extends X<B> {
public Y(B b) {
super(b);
}
public void foo() {
// here, this.a is of type B, without any type cast.
}
}
答案 1 :(得分:2)
我能想到的唯一理智的解决方案是#1的变体:向类Y
添加一个getter方法,该方法返回转换为类型B
的字段,并仅通过此方法访问该字段吸气。这只需要一次演员表,作为一个有益的副作用,它还会记录代码的哪些部分要求该字段实际上是B
。
答案 2 :(得分:2)
在我看来,解决方案#1是最正确的方式。如果你知道某个对象是一个特定的类,那么将它强制转换为该类是没有错的。如果你在做这个时做出假设是错误的,但根据你所说的,这不是一个假设。也许制作一个getter方法,简单地将底层字段转换为正确的类型并完成它?这样,你只需要施放一次(每个子类)。
如果字段以某种方式与彼此保持正确的最新状态,则解决方案#2将导致难以捉摸的运行时错误。这听起来像是最糟糕的解决方案。
解决方案#3仍然感觉像是糟糕的软件设计。如果存在一个方法,并且它不在抽象类中,并且您没有处于原型设计阶段,那么应该实现该方法。否则,你可能只是为用户(类)提供不必要的陷阱,给它一个误导性的界面。