parent 构造函数调用的方法的行为与 child 方法相同

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,它调用 addValue() 和(如 addValue() Base中定义的值相加10)此时的值应该是10。然后,调用 Derived 的 addValue() 使值变为 30(因为 Derived 中定义的 addValue() 将值增加 20)。但是,Base 调用它是 child 的 addValue()。有人可以解释发生了什么吗?

是的,这是多态性如何工作的一个很好的例子。

addValue 方法从未在此处被调用,因为子方法已被覆盖。它被称为virtual method invocation。因此,如果子方法被调用两次,结果将是 40.

您思维过程中的错误观念已加粗:

new Derived first calls new Base, which calls addValue() and (as addValue() defined in Base adds up value by 10) value should be 10 at that time. then, Derived's addValue() is called which makes value 30 (because addValue() defined in Derived adds value up by 20).

虽然 addValue 被放置在基础 class 构造函数中,它仍然在 this 上调用 addValue,像这样:

this.addValue();

嗯,什么是this?它是一个 Derived class 实例。派生的 class 的 addValue 有什么作用?它加了 20。这就是你得到 40 的原因。

是因为Derived隐式调用了super,但是会调用Derived中覆盖的addvalue。这就是为什么您不应该在构造函数中调用可覆盖方法的原因。

您可以通过在 main() 的第一行创建一个断点并让调试器向您展示这些步骤来找出这一点。

Java 在这方面与 C++ 的行为不同。在 C++ 中,当父构造函数执行时,对象被认为只是部分构造,因此它将执行父类的方法。在 Java 中,它将始终执行该方法的最派生实现。