简体   繁体   English

Java继承奇怪的行为

[英]Java Inheritance strange behaviour

The following code prints output as 40 instead of 30. I'm not able to figure out the solution. 以下代码将输出打印为40而不是30.我无法找出解决方案。 Please help with the code. 请帮助代码。

class Base {

  int value = 0;

    Base() {
      addValue();
    }

    void addValue() {
      value += 10;
    }

    int getValue() {
      return value;
    }
}

class Derived extends Base {

  Derived() {
    addValue();
  }

  void addValue() {
    value +=  20;
  }
}

public class Test{

  public static void main(String[] args) {
    Base b = new Derived();
    System.out.println(b.getValue());
  }
}

The implicit super reference in Derived constructor calls Base constructor which in turn calls method addValue() in the class Base results in value variable as 10 and then addValue() in the Derived class should add 20 to value 10. So the final output is 30. Derived构造函数中的隐式超级引用调用Base构造函数,它反过来调用类Base中的方法addValue()导致value变量为10,然后Derived类中的addValue()应该将20加到值10.因此最终输出为30 。

But the code prints 40. 但代码打印40。

The addValue method is overridden in the Derived class. Derived类中重写了addValue方法。 When a method is overridden, calling a method on an instance of this class always calls the overridden version, even when the call happens in the base class. 重写方法时,即使在基类中调用时,调用此类实例上的方法也始终调用重写版本。

Derived类中,方法void addValue()指向Derived中定义的方法,而不是Base定义的方法

Most probably when you extend the Base class 最有可能在扩展Base类时

class Derived extends Base {

  Derived() {

    addValue();

  }

  void addValue() { //here

    value +=  20;

  }

}

you put the method name same in the Base Class and this overrides the default one which is: 您将方法名称设置为Base Class相同,这将覆盖默认值:

   void addValue() {
      value += 10;
    }

So, the output is 40 -> 20 + 20 因此,输出为40 - > 20 + 20

As others have got there before me: addValue is overridden in Derived , as it is an accessible method with the same name and same parameter types. 正如其他人在我之前addValueaddValueDerived被覆盖,因为它是一个具有相同名称和相同参数类型的可访问方法。 Typically you would add the @Override annotation to the override method. 通常,您会将@Override注释添加到覆盖方法。 The method in the derived class even though the base class is still under construction. 即使基类仍在构建中,派生类中的方法。

Not all languages do the same thing. 并非所有语言都做同样的事情。 C++, for example, will not run overridden methods from derived class whilst the base constructor is still running. 例如,C ++不会在派生类中运行重写方法,而基本构造函数仍在运行。 The equivalent program in C++ does show 30. C ++中的等效程序确实显示30。

#include <iostream>

class Base {
public:
    int value;

    Base() : value(0) {
      addValue();
    }

    virtual void addValue() {
      value += 10;
    }

    int getValue() {
      return value;
    }
};

class Derived : public Base {
public:
  Derived() {
    addValue();
  }

  virtual void addValue() {
    value +=  20;
  }
};

int main() {
    Base *b = new Derived();
    std::cout << b->getValue() << std::endl;
}

addValue() is override in Derived class and you created a Derived class object. addValue()Derived类中被覆盖,您创建了一个Derived类对象。 So whenever the addValue() called by this instance. 所以每当addValue()被这个实例调用时。 Always methos is called of Derived class. 始终将方法称为Derived类。 So thats why addValue() of Derived class called twice. 这就是为什么Derived类的addValue()调用两次。 Once in the Base class constructor and second in Derived class constructor. 一次在Base类构造函数中,第二个在Derived类构造函数中。

As others discussed earlier Method Overriding property applies to method call in the base class well. 正如前面讨论的其他方法一样,Method Overriding属性适用于基类中的方法调用。

By this java applies Run Time Polymorphism ie, Based on the object that is invoked at run time, the method which is to be executed is decided. 通过这个java应用运行时多态性, 即,基于在运行时调用的对象,确定要执行的方法。 For eg, 例如,

  • If super class object is used to invoke the method, then super class method will be executed. 如果使用超类对象来调用该方法,则将执行超类方法。
  • If sub class object is used to invoke the method, then sub class method will be executed. 如果使用子类对象来调用该方法,则将执行子类方法。

If we don't want to override, we can make the parent method as private instead of default private package . 如果我们不想覆盖,我们可以将父方法设为private而不是默认私有包 Now we will be getting 30 as output. 现在我们将获得30作为输出。 As the method which cannot be inherited then it cannot be overridden 作为无法继承的方法,它不能被覆盖

class Base {

    int value = 0;

    Base() {
        addValue();
    }

    private void addValue() {
        value += 10;
    }

    int getValue() {
        return value;
    }
}

class Derived extends Base {

    Derived() {
        addValue();
    }

    void addValue() {
        value +=  20;
    }
}

public class Test{

    public static void main(String[] args) {
        Base b = new Derived();
        System.out.println(b.getValue());
    }
}

Now, the output is 30 . 现在,输出是30

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM