我试着理解继承概念,我有一个小问题。
我有两个A和B类:
public class B extends A
{
public B()
{
System.out.println ("B");
}
public void arik ()
{
System.out.println("Arik_B");
}
public void yosef ()
{
System.out.println ("Yosef");
}
public void superYosef()
{
super.yosef();
}
}
public class A
{
public A()
{
System.out.println ("A");
}
public void arik ()
{
System.out.println ("Arik_A");
}
public void yosef ()
{
arik();
}
}
主:
A ab = new B();
((B) ab).superYosef();
行A ab = new B();
将打印A B,这很清楚。
但是行((B) ab).superYosef();
打印Arik_B
并且我不明白为什么。
在运行ab
之前输入A
并在运行它时B需要打印Yosef
答案 0 :(得分:5)
在this
上调用实例方法时,唯一重要的是调用它的对象的类型。此类型仅在运行时中已知。
在super
上调用实例方法时,动态调度不适用。该方法在编译时选择。
在您的代码中:
new B();
并致电B.superYosef();
super.yosef();
会静态调用A.yosef()
(不受动态调度影响); A.yosef()
调用this.arik()
- 与上述不同,调用this
的方法受动态调度影响; this
的类型为B
,因此调用方法B.yosef()
。答案 1 :(得分:5)
当你这样做时
A ab = new B();
然后是ab
类型的变量A
,但它引用的实际对象是B
类型。对象的实际类型决定了将调用哪个方法,而不是变量的类型。
因此,当您在ab
上调用已在类B
中重写的任何方法时,将调用类B
中的版本。
让我们看看这里发生了什么:
((B) ab).superYosef();
您需要强制转换,因为方法superYosef
仅在类B
中定义。
该方法调用super.yosef();
,它将调用类yosef
中的A
方法。 A.yosef
调用arik
,并在类B
中覆盖此方法。请注意,我们在一个实际为B
的对象上调用了该方法,因此调用arik
中的B
方法,打印Arik_B
。
答案 2 :(得分:3)
调用方法时:
((B) ab).superYosef();
ab
引用引用的实际实例仅属于类B
。进一步说,此调用将调用类superYosef()
中的方法B
方法。现在,我们来看看那个方法:
public void superYosef()
{
super.yosef();
}
这将调用类yosef()
中的A
方法。由于super
。该实例仍为B
。然后在yosef()
方法中:
public void yosef ()
{
arik(); // equivalent to `this.arik();`
}
在这里,您可以参考this
持有对类B
实例的引用。您调用arik()
,它在类B
中被覆盖,因此调用类arik()
的方法B
。唯一重要的是,实际对象的类型为B
。
答案 3 :(得分:0)
因为您使用类B
覆盖方法arik
,所以这就是它在B类中访问此方法的原因。
您的ab
变量仍为B
。