1. Но и это еще не все
Предположим, в классе Cow
есть метод printAll()
, который вызывает два других метода. Тогда код будет работать так:
Код | Описание |
---|---|
|
|
|
На экран будет выведена надпись:
|
Обратите внимание: когда вызывается метод printAll()
, написанный в классе Cow
, у объекта типа Whale
, используется метод printName
класса Whale
, а не Cow
.
Главное — не в каком классе написан метод, а какой тип (класс) объекта, у которого этот метод вызван.
Наследовать и переопределять можно только нестатические методы. Статические методы не наследуются и, следовательно, не переопределяются.
Вот как выглядит класс Whale
после применения наследования и переопределения методов:
|
Вот как выглядит класс Whale после применения наследования и переопределения метода. Ни о каком старом методе printName мы и не знаем. |
2. Приведение типов
Тут есть еще более интересный момент. Т.к. класс при наследовании получает все методы и данные класса-родителя, объект этого класса разрешается сохранять (присваивать) в переменные класса-родителя (и родителя родителя, и т.д., вплоть до Object
). Пример:
Код | Описание |
---|---|
|
На экран будет выведена надпись:
|
|
На экран будет выведена надпись:
|
|
На экран будет выведена надпись:
Метод toString() унаследован от класса Object
|
Это очень ценное свойство: немного позже вы поймете, как это использовать на практике.
3. Вызов метода объекта
При вызове метода у переменной, реальный метод вызывается у объекта. Этот механизм называется динамической диспетчеризацией методов.
Вот как это выглядит:
Код | Описание |
---|---|
|
На экран будет выведена надпись:
|
|
На экран будет выведена надпись:
|
Обратите внимание, что на то, какой именно метод printName()
вызовется, от класса Cow
или Whale
, влияет не тип переменной, а тип объекта, на который она ссылается.
В переменной типа Cow
сохранена ссылка на объект типа Whale
, и будет вызван метод printName()
, описанный в классе Whale
.
Это не очень очевидно. Запомните главное правило:
Набор методов, которые можно вызвать у переменной, определяется типом переменной. А какой именно метод/какая реализация вызовется, определяется типом/классом объекта, ссылку на который хранит переменная.
Вы будете постоянно сталкиваться с этим, так что чем раньше запомните, тем лучше.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ