Не могли бы вы проанализировать вывод этого кода JAVA о наследовании - PullRequest
0 голосов
/ 09 июля 2019

Я добавил свой вопрос в комментарии к коду.

class Parent{
    int num =9; //I think num in Parent class is overrided by the num in Child class. why is the num in the first line of output is still 9?
    { //code block
        System.out.println("Parent constructor code..."+num);
    }

    Parent(){
        System.out.println("Parent constructor run"); 
        show(); //why does this method here invoke the show() method in Child class?
    }

    void show() {
        System.out.println("Parent show..."+num);
    }
}

class Child extends Parent{
    int num = 8; 
    {
        System.out.println("Child constructor code..."+num);
        num = 10;
    }

    Child(){ 
        System.out.println("Child constructor run"); 
        show(); 
    }

    void show() {
        System.out.println("Child show..."+num);
    }
}

public class Test {

    public static void main(String[] args) {
        new Child();
    }

}

вывод:

Код родительского конструктора ... 9
Запуск родительского конструктора
Дочернее шоу ... 0
Дочерний конструктор код ... 8
Дочерний конструктор запускается
Дочернее шоу ... 10

спасибо, ребята!Я понял, что это проблема скрытого и скрытого изменения.

Ответы [ 3 ]

2 голосов
/ 09 июля 2019

Порядок строительства объекта:

  1. объявление и инициализация переменной
  2. блок конструктора экземпляра
  3. Конструктор

Если у класса есть родительский класс, такой же порядок выполняется для родительского до того, как для фактического класса .

родитель первый

int num = 9

оценивается первым, num устанавливается на 9 (родительский 1.)

Код родительского конструктора ... 9

Блоки инициализатора экземпляра выполняются перед конструктором (родительским 2).

Запуск родительского конструктора

Конструктор называется (родительский 3.)

Детское шоу ... 0

Конструктор Parent вызывает show(). show() переопределяется, поэтому вызывается Child.

Дочерние номера 1. и 2. еще не были вызваны, поэтому переопределение num в Child по-прежнему равно 0. * 1

потом ребенок

int num = 8

Child х 1. оценивается

Код дочернего конструктора ... 8

Child s 2. num устанавливается на 10 после этого.

Выполнение дочернего конструктора

Child х 3.

Детское шоу ... 10

Конструктор

Child вызывает show().

* 1

Вот почему вызов не-1088 * методов в конструкторе очень опасен. Методы имеют тенденцию полагаться на инициализируемую переменную-член; их нет в этом месте.

Если бы это была не примитивная переменная, вы вполне могли бы столкнуться с NullPointerException, если ваш метод пытается получить к ней доступ.

1 голос
/ 09 июля 2019

Когда java создает дочерний класс, он должен вызвать super(), чтобы инициализировать родительский класс - так он может создавать частные поля в суперклассе или выполнять другие действия. (Это не создает объект родительского класса.) Вот почему вы видите Parent constructor code...9 - он вызывает родительский код и печатает родительский num.

Поскольку вы создаете дочерний класс, дочерний show() называется в родительском конструкторе . Вот почему опасно вызывать неконечные методы в конструкторе - если дочерний процесс переопределяет их, вместо него будут вызываться дочерние методы.

Дочерний элемент num равен 0, потому что Java инициализирует переменные-члены значениями по умолчанию , и ваш код еще не имел возможности установить его на 10.

Что касается вашего дочернего кода, num не переопределяется, он скрыт - только методы могут быть переопределены. Вот почему show() вашего ребенка отображает его как 10, как только оно правильно инициализировано. Если вы хотите получить доступ к родительской переменной, вы можете сделать это с помощью super.num, но это часто считается плохой практикой, поскольку это может вызвать путаницу.

0 голосов
/ 09 июля 2019

Я думаю, это потому, что ваш конструктор автоматически вызывает конструктор суперкласса. (для нашего первого вопроса.) тем не менее, вы переопределяете show, поэтому, когда он встречает этот метод, он вызывает дочерний метод

...