Наследование Java странное поведение - PullRequest
0 голосов
/ 12 октября 2018

Следующий код печатает вывод как 40 вместо 30. Я не могу найти решение.Пожалуйста, помогите с кодом.

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());
  }
}

Неявная супер-ссылка в конструкторе Derived вызывает конструктор Base, который, в свою очередь, вызывает метод addValue() в классе Base, в результате чего значение переменной равно 10 итогда addValue() в классе Derived должно добавить 20 к значению 10. Таким образом, конечный результат равен 30.

Но код печатает 40.

Ответы [ 6 ]

0 голосов
/ 12 октября 2018

Как и другие до меня: addValue переопределяется в Derived, так как это доступный метод с тем же именем и теми же типами параметров.Обычно вы добавляете аннотацию @Override в метод переопределения.Метод в производном классе, хотя базовый класс все еще находится в стадии разработки.

Не все языки делают одно и то же.C ++, например, не будет запускать переопределенные методы из производного класса, пока базовый конструктор все еще работает.Эквивалентная программа на 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;
}
0 голосов
/ 12 октября 2018

Как уже обсуждалось ранее, свойство переопределения метода применяется к вызову метода в лунке базового класса.

К этому java применяется полиморфизм времени выполнения , т. Е. На основе объекта, который вызывается во время выполнения,определяется метод, который должен быть выполнен. Например,

  • Если для вызова метода используется объект суперкласса, то будет выполнен метод суперкласса.
  • Если для вызова метода используется объект подкласса, будет выполнен метод подкласса.

Если мы не хотим переопределять, мы можем сделать родительский метод какprivate вместо значения по умолчанию личный пакет .Теперь мы получим 30 в качестве выхода. Поскольку метод, который не может быть унаследован, он не может быть переопределен

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());
    }
}

Теперь, вывод равен 30 .

0 голосов
/ 12 октября 2018

addValue() переопределено в классе Derived, и вы создали объект класса Derived.Поэтому всякий раз, когда addValue() вызывается этим экземпляром.Всегда метод называется класса Derived.Так вот почему addValue() из производного класса вызывается дважды.Один раз в конструкторе класса Base и второй в конструкторе класса Derived.

0 голосов
/ 12 октября 2018

Скорее всего, когда вы расширяете базовый класс

class Derived extends Base {

  Derived() {

    addValue();

  }

  void addValue() { //here

    value +=  20;

  }

}

, вы помещаете то же имя метода в Base Class, и оно переопределяет значение по умолчанию:

   void addValue() {
      value += 10;
    }

Таквыходной сигнал 40 -> 20 + 20

0 голосов
/ 12 октября 2018

В классе Derived метод void addValue() указывает на метод, определенный в Derived, а не в Base

0 голосов
/ 12 октября 2018

Метод addValue переопределен в классе Derived.Когда метод переопределяется, вызов метода в экземпляре этого класса всегда вызывает переопределенную версию, даже если вызов происходит в базовом классе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...