Почему наследование работает таким образом в Java? - PullRequest
0 голосов
/ 26 мая 2019

Я новичок в Java и пытаюсь понять, что произойдет, когда я назначу экземпляр дочернего класса переменной экземпляра родительского класса, имитируя следующую программу.

public class ConfusionWithInheritance {

    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        DerievedClass d = new DerievedClass();
        BaseClass b = BaseClass.class.cast(d);
        BaseClass b1 = new DerievedClass();
        b.doSomeJob();
        b.printMagic(); //-> Compiler shouted me that it didn't know this method here.
    }
}
class BaseClass {
    public void doSomeJob() {
        System.out.println("Printing Value X");
    }
}
class DerievedClass extends BaseClass {
    public void doSomeJob() {
        System.out.println("Printing Value Y");
    }
    public void printMagic() {
        System.out.println("Printing magic...");
    }
}

1) Почему мне разрешено присваивать экземпляр дочернего класса переменной родительского типа?

2) Из этого ответа объясняется, что, поскольку я говорю черновой вариант класса - родительский класс - он знает только методы родительского класса. Тогда почему он печатает значение в методе дочернего класса, когда я вызываю childInstance.doSomeJob ()?

Ответы [ 2 ]

1 голос
/ 26 мая 2019

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

В время компиляции , методы доступные - это те, которые относятся к типу объекта объявлено с.
В время выполнения , методы , вызванные , относятся к типу, для которого объект создан с.

Таким образом, для объекта, объявленного как тип BaseClass и созданного как тип DerivedClass, методы доступные будут такими же, как в BaseClass, т.е.doSomeJob (), но метод вызвал тот, который используется в DerivedClass.

1 голос
/ 26 мая 2019

При создании объекта:

BaseClass b1 = new DerievedClass();

То, что мы говорим:

ReferenceType variableName = new ConcreteImplementation();

Думайте об этом как о ReferenceType, обеспечивающем основу для нового Объекта.

Когда объект создается, он обращается к этому ReferenceType и создает объект со всеми методами в ReferenceType как скелет.

Затем мы смотрим на ConcreteImplementation для реализации методов. Поэтому компилятор обращается к ConcreteImplementation, чтобы заполнить все методы.

В конечном объекте реализовано только то, что определено в ReferenceType.

Думайте о приведении как об изменении ReferenceType уже существующего объекта

со строкой:

DerievedClass d = new DerievedClass();

ReferenceType - это DeriveClass, поэтому мы берем все методы из DerivedClass и заполните их реализацией из ConcreteImplementation, которая является DerivedClass.

Затем мы приводим DeriveClass d к BaseClass b.

BaseClass b = BaseClass.class.cast(d);

d имеет всю реализацию из DerivedClass, но скаффолд получен из базового класса ReferencType, поэтому мы не можем вызвать printMagic потому что он не существует в BaseClass.

Имеет ли это смысл?

Надеюсь, это поможет

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