Страницы

Поиск по вопросам

понедельник, 23 декабря 2019 г.

Tricky inheritance (Хитрое наследование)

#java


Итак, продолжим экскурс в Java-задачки. Очередная из тех же источников, правда, она
может показаться весьма простой для бывалых или для тех, у кого под рукой компилятор.
Код:
public class A {
    public A() {
        myMethod();
    }
    public void myMethod() {
        Date date = new Date();
    }
}

public class B extends A {
    private Date date = new Date();

    public B() {
        date = new Date();
    }

    @Override
    public void myMethod() {
        System.out.println(date);
    }

    //...
    public static void main(String[] args) {
        B sub = new B();
        sub.myMethod();
    }
}

Вопросы:

Каков же вывод данной программы?
Поясните свой предыдущий ответ

Для изучающих ООП задачка будет весьма полезной. Кроме того, можете добавить свои
соображения по поводу того, почему данная программа не является отказоустойчивой (robust).    


Ответы

Ответ 1



Признаюсь сразу, ответ получен с помощью компилятора. null Tue Oct 11 00:19:35 MSD 2011 Все дело в том, что вызываемый из конструктора A myMethod() оказывается одноименным методом конструктора B, а в это время поле date класса B еще не инициализировано датой. Понятно, что память выделена и обнулена. Вторая строчка вывода это ожидаемый результат вызова sub.myMethod() из main(). Порядок вызовов такой: конструктор A, из него метод myMethod() класса B (он переопределяет myMethod() класса A), конструктор B (инициализирует дату) и наконец sub.myMethod(); Локальный для класса A метод myMethod() вообще не вызывается. Директива @Override в данном случае никак себя не проявляет (сигнатуры одинаковы). Видимо это пример того, что не надо делать методы с одинаковыми именами (не только сигнатурами !), вызываемыми из конструкторов. Да, Java это язык, на котором элегантно пишутся головоломки.

Ответ 2



В дополнение к ответу avp Инициализация состояния класса путем вызова переопределяемого метода - потенциальная угроза неправильной инициализации родительского класса, и, как следствие, непрогнозируемой работы производного класса. Кроме того, возможна утечка недоинициализированного экземпляра через this вследствие его передачи другим объектам и/или потокам из переопределяемого метода.

Комментариев нет:

Отправить комментарий