воскресенье, 12 марта 2017 г.

A programmer: Java #6: A a = new B();

Долго не мог разобраться с тем, что означает выражение

A a = new B(); // B extends A

Первый мой ответ на этот вопрос был таким:

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

Класс-наследник, кроме собственных методов, имеет все методы классов-родителей. Последние могут быть переопределны в классе-наследнике:

Пусть у класса А есть метод do() { // реализация для А};
И у класса В есть метод do() { // реализация для В}

Соответственно, в нашем случае - для a.do(); будет выбрана реализация для В:

Class Животное {
    издатьЗвук() {
        "Звук-Звук";
    };
}

Class Cобака extends Животное {
    издатьЗвук() {
        "Гав-Гав";
    };
}
Животное животное = new Собака();
животное.издатьЗвук();

Результат: "Гав-Гав".

Но возникал вопрос: а что в данном случае происходит с полями? Будут это поля из А или из В?

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

Но правильный ответ - нет, потому что в нашем случае объект а - это объект класса В, который приведен к типу А. Что это значит? Мне посоветовали читать "Философию Java", но хороший ответ нашел тут: "Преобразование типов".

Это значит, что если а - это объект класса В, то поля относятся к классу В. А "приведение ссылочных типов" означает только то, что в приведенном объекте не видны те поля, которых нет в классе-родителе (хотя они есть!). Следовательно, логика тут такая - обрезать то, чего нет в родителе, а в оставшихся полях будут значения из класса-наследника.

Другими словами, если у Животного не предусмотрен Хвост (а предусмотрен только у Собаки), то у нас будет Собака, которой нельзя использовать Хвост (хотя он есть). А если у Животного Хвост предусмотрен, то это будет Хвост Собаки.


UPD: На самом деле поля будут и от А, и от В. Но в случае прямого приведения типов ((А) а) поля от В будут скрыты (как если бы их не было). Другими словами Хвост будет не Хвостом Собаки, а Хвостом Животного.

На эту тему также посмотреть можно здесь, здесь, здесь и здесь.

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