1. Але це ще не все

Припустімо, у класі Cow є метод printAll(), який викликає два інші методи. Тоді код працюватиме так:

Код Опис
class Cow
{
   public void printAll()
   {
      printColor();
      printName();
   }

   public void printColor ()
   {
      System.out.println("Я — біла");
   }

   public void printName()
   {
      System.out.println("Я — корова");
   }
}

class Whale extends Cow
{
   public void printName()
   {
      System.out.println("Я — кит");
   }
}
public static void main(String[] args)
{
   Whale whale = new Whale ();
   whale.printAll();
}
На екран буде виведено напис:
Я — біла
Я — кит

Зверніть увагу: коли для об'єкта типу Whale викликається метод printAll(), успадкований від класу Cow, використовується метод printName класу Whale, а не класу Cow.

Неважливо, в якому класі створено метод, головне — до якого класу належить об'єкт (тобто тип об'єкта), для якого цей метод викликано.

Успадковувати й перевизначати можна тільки нестатичні методи. Статичні методи не успадковуються і тому не перевизначаються.

Отакий вигляд має клас Whale після успадкування та застосування перевизначення методів:

class Whale
{
   public void printAll()
   {
      printColor();
      printName();
   }

   public void printColor()
   {
      System.out.println("Я - біла");
   }

   public void printName()
   {
      System.out.println("Я - кит");
   }
}
Отакий вигляд має клас Whale після успадкування та застосування перевизначення методу. Ні про який старий метод printName ми навіть і не знаємо.

2. Перетворення типів

Є ще один дуже цікавий момент. Оскільки під час успадкування клас отримує всі методи й дані батьківського класу, об'єкт цього класу можна присвоювати (зберігати) змінним батьківського класу (а також змінним батька батьківського класу і т. д. аж до Object). Приклад:

Код Опис
public static void main(String[] args)
{
   Whale whale = new Whale();
   whale.printColor();
}
На екран буде виведено напис:
Я — біла
public static void main(String[] args)
{
   Cow cow = new Whale();
   cow.printColor();
}
На екран буде виведено напис:
Я — біла
public static void main(String[] args)
{
   Object o = new Whale();
   System.out.println(o.toString());
}
На екран буде виведено напис:
Whale@da435a.

Метод toString() успадковано від класу Object

Це дуже цінна властивість, і згодом ми пояснимо, як це використовувати на практиці.


3. Виклик методу об'єкта

Коли здійснюється виклик методу для змінної, фактично цей метод викликається для об'єкта. Цей механізм називається динамічною диспетчеризацією методів.

Отакий вигляд це має:

Код Опис
public static void main(String[] args)
{
   Whale whale = new Whale();
   whale.printName();
}
На екран буде виведено напис:
Я — кит
public static void main(String[] args)
{
   Cow cow = new Whale();
   cow.printName();
}
На екран буде виведено напис:
Я — кит

Зверніть увагу, що тип змінної не впливає на те, який саме метод printName() — класу Cow чи класу Whale — буде викликано: вибір методу визначається не типом змінної, а типом об'єкта, на який посилається ця змінна.

У змінній типу Cow збережено посилання на об'єкт типу Whale, і буде викликано метод printName(), який описано в класі Whale.

Це не відразу зрозуміло. Запам'ятайте головне правило:

Набір методів, які можна викликати для змінної, визначається типом змінної. А який саме метод чи яку його реалізацію буде викликано, визначається типом (класом) об'єкта, посилання на який зберігає змінна.

Ви будете постійно стикатися з цим, тож що раніше все це запам'ятаєте, то краще.