对于那些不支持从多个类继承的语言(不确定这里是否重要,只是认为我会详细说明),这是一个普遍的OOP问题,如Java:
好的,你有基类:
class Base {}
class Derived extends Base
{
SomeMethod(){}
}
Main()
{
Base baseInstance = new Base();
Derived derivedInstance = new Derived();
baseInstance = derivedInstance;
baseInstance.someMethod(); <<<<<< this does not work. why?
}
为什么在将baseInstance设置为derivedInstance时,是否无法调用Derived类中定义的方法?
由于您将baseInstance设置为derivedInstance,您是否可以访问此方法?
答案 0 :(得分:6)
作为基类输入的变量不能设定有关子类的方法。例如,对于所有编译器都知道,baseInstance
可以保留对Base
或SomeOtherClass extends Base
的引用。现在,您可以说在这种情况下编译器可以解决它,但是:不是编译器做的。编译器的规则很简单:如果您输入的变量为Base
,则只能使用Base
上已知的内容。
如果你想使用特定子类的专门方法,那么你需要让编译器执行带类型检查的强制转换,即
Derived special = (Derived)baseInstance; // I'm using C# syntax here,
special.someMethod(); // but should be similar or identical
答案 1 :(得分:1)
这一行
baseInstance = derivedInstance;
未将baseInstance
设置为Derived
类型。它仍然是Base
类型。
如果someMethod()
是Base
中定义的方法,则只能在someMethod
类型的对象上调用Base
。编译器不知道更多派生方法。
答案 2 :(得分:1)
在java 实例是在运行时创建,因此实际的类实例在运行时得到解析,而不是在编译期间解析。
因此,编译器始终查看引用类型以确定引用变量可以引用哪些方法或成员。
在您的情况下,baseInstance = derivedInstance;
即使被引用的实际类是Base
的子类,编译器也只是假设它是Base
类型。显然,Base
类没有someMethod();
,因此它不允许您调用它。
作为一种解决方法,你可以试试这个:
if(base instanceof Derived) {
// Downcast it before calling
((Derived)baseInstance).someMethod();
}