2017-01-01 6 views
-1

В принципе, у меня есть код, который сводится к приведенному ниже. При запуске, я ожидаю, что следующий вывод:Изменение переменной дочернего экземпляра в режиме переопределения

Parent doing work 
Child overriding. variable=5 
Child overriding. variable=10 
Child childMethod(). variable=10 

Parent doing work 
Child2 overriding. variable=5 
Child2 overriding. variable=10 
Child2 childMethod(). variable=10 

Что я получаю следующий вывод:

Parent doing work 
Child overriding. variable=0 
Child overriding. variable=10 
Child childMethod(). variable=5 

Parent doing work 
Child2 overriding. variable=0 
Child2 overriding. variable=10 
Child2 childMethod(). variable=10 

Моя теория для этого несоответствия является то, что variable привыкает «перед» объявлен. Это основано на

  1. variable имеет свое первоначальное значение, установленное в 0 в соответствии с выходным (INT умолчанию)

  2. В случае класса Child, variable, казалось бы, вновь обретает свою предполагаемую первоначальную стоимость 5.

Правильно ли это, что variable используется «до», это объявлено? Кроме того, есть ли какие-то причины, почему это ожидаемое поведение?


public static void main(String[] params) { 
    Parent child = new Child(); 
    child.childMethod(); 

    System.out.println(); 

    Parent child2 = new Child2(); 
    child2.childMethod(); 
} 

public static abstract class Parent { 

    public Parent() { 
     method(); 
    } 

    public void method() { 
     System.out.println("Parent doing work"); 
    } 

    abstract void childMethod(); 
} 

public static class Child extends Parent { 
    int variable = 5; 

    @Override 
    public void method() { 
     super.method(); 
     System.out.println("Child overriding. variable=" + variable); 
     variable = 10; 
     System.out.println("Child overriding. variable=" + variable); 
    } 

    public void childMethod() { 
     System.out.println("Child childMethod(). variable=" + variable); 
    } 

} 

public static class Child2 extends Parent { 
    int variable; 

    @Override 
    public void method() { 
     super.method(); 
     System.out.println("Child2 overriding. variable=" + variable); 
     variable = 10; 
     System.out.println("Child2 overriding. variable=" + variable); 
    } 

    public void childMethod() { 
     System.out.println("Child2 childMethod(). variable=" + variable); 
    } 

} 
+0

Это плохой дизайн кода. Вы не должны пытаться объяснить это, просто забудьте об этом. – brummfondel

+2

Скорее всего, уже ответил много раз - вы искали о поведении вызова виртуального метода из конструктора? –

+1

Переопределенный метод 'method' вызывается до инициализации переменной' variable'. Используйте отладчик, чтобы узнать, что происходит шаг за шагом. Чтобы избежать подобных ситуаций, вызывайте только конечные методы в конструкторах. –

ответ

4

Это довольно просто. Детский класс инициализируется только после завершения родительского класса. Проверка или изменение дочернего состояния во время конструктора родителя означает, что вы взаимодействуете с неинициализированными полями.

В вашем случае вы читаете значение по умолчанию 0, и ваши изменения отбрасываются после инициализации дочернего элемента.