提问人:GeorgeTheGood 提问时间:7/23/2017 更新时间:7/23/2017 访问量:1161
父构造函数调用的方法表现为子方法
Method called by parent constructor behaves as child method
问:
我正在 java 中测试一些多态性,我的代码如下所示:
class Base {
int value = 0;
public Base(){
System.out.println("Came Here And Value is: " + value);
addValue();
}
String addValue(){
System.out.println("Calling Bases' addValue and value is currently: " + value);
value += 10;
return "";
}
int getValue(){
return value;
}
}
class Derived extends Base{
public Derived(){
System.out.println("Calling Derived constructor and value currently is: " + value);
addValue();
}
String addValue(){
System.out.println("Came to Deriveds' addValue and value now is: " + value);
value += 20;
return "";
}
int getValue(){
return value;
}
}
public class MyClass {
public static void main(String [] args){
Base b = new Derived();
System.out.println(b.getValue());
}
}
所以这里的问题是,它打印 40,但我猜它应该打印 30。我的想法是:new Derived 首先调用 new Base,它调用 和 (定义在 Base 中将值加以 10)当时值应该是 10。然后,调用 Derived's,使值为 30(因为 Derived 中的定义将值增加了 20)。但相反,Base 调用了它子的 .有人可以解释发生了什么吗?addValue()
addValue()
addValue()
addValue()
addValue()
答:
是的,这是多态性如何工作的一个很好的例子。
由于重写了子方法,因此此处从不调用父方法。这称为虚拟方法调用。因此,如果子方法被调用两次,结果将是 。addValue
40
评论
你思维过程中的误解被加粗了:
new Derived 首先调用 new Base,后者调用 addValue() 和 (因为 Base 中定义的 addValue() 将 value 相加 10)此时 value 应为 10。 然后,调用 Derived 的 addValue(),使值为 30(因为 Derived 中定义的 addValue() 将值增加 20)。
虽然被放置在基类构造函数中,但它仍然调用 ,如下所示:addValue
addValue
this
this.addValue();
嗯,什么是?它是一个类实例。派生类有什么作用?它增加了 20。这就是为什么你得到 40 个。this
Derived
addValue
评论
addValue
Base.addValue
这是因为 Derived 对 super 进行了隐式调用,但它将调用 Derived 中覆盖的 addvalue。这就是为什么不应在构造函数中调用可重写方法的原因。
您可以通过在 main() 的第一行上创建一个断点来找到这一点,并让调试器向您显示步骤。
评论
在这方面,Java 的行为与 C++ 不同。在 C++ 中,当父构造函数执行时,对象仅被视为部分构造,因此它将执行父构造函数的方法。在 Java 中,它将始终执行该方法最派生的实现。
评论
Base.addValue()
Base()
Derived.addValue()
Derived()
评论