我是Java的新手,我试图通过模拟以下程序来了解将子类实例分配给父类实例变量时会发生什么情况。
public class ConfusionWithInheritance {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
DerievedClass d = new DerievedClass();
BaseClass b = BaseClass.class.cast(d);
BaseClass b1 = new DerievedClass();
b.doSomeJob();
b.printMagic(); //-> Compiler shouted me that it didn't know this method here.
}
}
class BaseClass {
public void doSomeJob() {
System.out.println("Printing Value X");
}
}
class DerievedClass extends BaseClass {
public void doSomeJob() {
System.out.println("Printing Value Y");
}
public void printMagic() {
System.out.println("Printing magic...");
}
}
1)为什么允许将子类的实例分配给父类型变量?
2)从这个Stephen Cleary那里可以解释,因为我要告诉类的蓝图是父类,所以它只知道父类中的方法。那么为什么在我调用childInstance.doSomeJob()时在子类的方法中打印值?
答案 0 :(得分:2)
创建对象时:
BaseClass b1 = new DerievedClass();
我们要说的是:
ReferenceType variableName = new ConcreteImplementation();
将其视为提供新对象支架的ReferenceType。
创建对象时,它会查找此ReferenceType并创建一个对象,并将ReferenceType中的所有方法作为框架。
然后我们看一下具体实现方法的实现。 因此,编译器将使用ConcreteImplementation来填充所有方法。
在最终对象中仅实现ReferenceType中定义的内容。
请考虑将其转换为更改现有对象的ReferenceType
所在行:
DerievedClass d = new DerievedClass();
ReferenceType是DerievedClass,所以我们采用DerivedClass的所有方法 并使用DerivedClass的ConcreteImplementation中的实现填充它们。
然后将DerievedClass d强制转换为BaseClass b。
BaseClass b = BaseClass.class.cast(d);
d具有DerivedClass的所有实现,但支架来自ReferencType BaseClass,因此我们不能调用printMagic 因为它在BaseClass中不存在。
这有意义吗?
希望有帮助
答案 1 :(得分:2)
这归结为编译时间和运行时之间的差异。
编译时,可用方法是声明了对象的类型。
在运行时中,调用的方法是对象被实例化的类型的那些方法。
因此,对于一个声明为BaseClass类型并实例化为DerivedClass类型的对象,方法 available 将是BaseClass中的那些方法。 doSomeJob(),但是方法调用是DerivedClass中的方法。