0

所以我遇到了一个问题,两天来一直在绞尽脑汁想弄清楚,所以我想是时候寻求帮助了。

所以在这里我的问题是我有一个抽象类 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 中的所有公共成员,正确的?还是数组的规则不同?

ps 我对变量使用protected,对我的方法使用public。

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

4

2 回答 2

1

如果该类具有该方法的定义,则只能在该类上调用该方法,因此如果A未定义getNum(),则无法调用getNum()它。这些是编译器的规则,而不是运行时的规则;A a实际上可能是 a C,但编译器无法知道这一点。如果你想调用's 方法,你需要告诉编译器那a是 a ,例如,如果事实证明这实际上不是 a那么你会得到一个 run-time 。为了防止这种情况,您可以使用运算符,CC((C)a).getNum();aCClassCastExceptioninstanceof

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

但像这样的演员表通常表明设计不佳。但是如果你真的想这样做,使用它instanceof比 catch ClassCastExceptions 快得多(大约快一个数量级)。

于 2013-04-17T01:25:16.450 回答
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,而不关心任何子类中定义的方法。

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

如果您确实需要对数组中的项目执行不同的操作,具体取决于它们的类型A是 ,B还是C,那么您可以查看访问者模式

于 2013-04-17T01:45:27.207 回答