在Java中遇到动态绑定问题

时间:2013-04-17 01:13:46

标签: java arrays dynamic binding polymorphism

所以我遇到了一个问题,并且已经破坏了我的大脑试图找出两天,所以我认为是时候得到一些帮助了。

所以在这里我的问题是我有一个抽象类B扩展抽象类A,我没有覆盖B中的任何方法或任何东西,但指定更专业的行为,变量等。

现在这里是我的问题所在,我有一个第三类让我们说C类,实现所有正确的方法,可能会覆盖一些(我使用了@Override符号所以我知道它做得对),以及也许可以添加一些自己的方法和变量。

现在这很好,但是当我尝试创建一个A类型的数组时,我想使用动态绑定,这样我就可以添加类型为C的对象,或者其他任何可以返回A的对象。

A[] AObjects = new A[3];
Aobject[0] = new C();
so on and so forth

现在假设我有一个像getNum()的方法;在只有C的C里面,它一直告诉我getNum();我尝试使用它时未在类型A中定义。我错过了什么吗?因为我的理解方法仅在运行时绑定,所以我应该能够获取类型A的引用变量,并将其分配给类型C的对象,并且能够调用C中的所有公共成员,对?或者数组的规则是不同的?

p.s我对我的变量使用了protected,对我的方法使用了public。

任何帮助将不胜感激! :)谢谢

2 个答案:

答案 0 :(得分:1)

如果类具有该方法的定义,则只能在类上调用方法,因此如果A未定义getNum(),则无法在其上调用getNum() 。这些是编译器的规则,而不是运行时的规则; A a实际上可能是C,但编译器无法知道这一点。如果要调用a的方法,您需要告诉编译器CC((C)a).getNum();如果事实证明a实际上不是C,那么您将获得运行时ClassCastException。为防止这种情况,您可以使用instanceof运算符

if(a instanceof C)
    ((C)a).getNum();
else 
    // do something else

但是像这样的演员经常表明设计不好。但是如果你真的想这样做,使用instanceof比抓住ClassCastException要快得多(大约快一个数量级)。

答案 1 :(得分:0)

如果您有一个A[]类型的数组并向其添加C类型的对象,那么您实际上将其向上转发到A。所以当你做这样的事情时

A[] aObjects = new A[3];
aObjects[0] = new C();
aObjects[0].someMethodOnlyDefinedForC(); // <-- Compile error

您可以将编译器解释为:

C objectOfTypeC = new C();
A objectCastToTypeA = (A) objectOfTypeC; // Upcasting to A
A[] aObjects = new A[3];
aObjects[0] = objectCastToTypeA;
objectCastToTypeA.someMethodOnlyDefinedForC(); // <-- Compile error

通过将它添加到A[]数组中,您告诉编译器只关心类A中定义的公共接口,而不关心任何子类中定义的方法。

当然,如果您可以保证某个索引处的某个项目始终是C类型,那么您可以像((C) aObjects[0]).methodOnlyDefinedForC()那样向下转发,但是以这种方式欺骗类型系统是一个一点代码味道。确定这些类是否真的应该相互继承,或者是否可以更好地利用多态来实现所需。

如果您确实需要对数组中的项执行不同的操作,具体取决于它们是AB还是C,那么您可能会查看Visitor Pattern