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

Змінні вказівних типів (класів) теж можна перетворювати на різні типи. Однак це діє лише в межах однієї ієрархії типів. Розгляньмо простий приклад. Припустімо, у нас є така ієрархія класів: класи, показані нижче, успадковуються від класів, показаних вище.

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

Перетворення вказівних типів, так само як і примітивних, поділяються на розширення й звуження.

Ми бачимо, що клас Кіт успадковано від класу ДомашняТварина, а клас ДомашняТварина своєю чергою успадковано від класу Тварина.

Напишімо такий код:

Тварина котик = new Кіт();

Це перетворення є розширенням типу: його ще називають неявним. Ми розширили посилання котик, і тепер воно посилається на об'єкт типу Кіт. У разі такого перетворення ми не зможемо через посилання котик викликати методи, які має клас Кіт, але яких не має клас Тварина.

Перетворення-звуження (або явне перетворення) відбувається у зворотному напрямку:

Кіт киця = (Кіт) котик;

Ми явно вказали, що хочемо перетворити посилання, що зберігається у змінній котик (типу Тварина), на тип Кіт.


18
Задача
Java Syntax Zero,  18 рівень4 лекція
Недоступна
Космічна одіссея ч. 1
Перед тим, як космічний корабель стартує у Всесвіт, побтрібно запросити на борт екіпаж, який складатиметься із 2 людей, 1 собаки й 1 кота. У методі createCrew() додай потрібну кількість екземплярів відповідних класів до списку astronauts. Підказка: Щоб додати до одного списку об'єкти різних класів,
18
Задача
Java Syntax Zero,  18 рівень4 лекція
Недоступна
Космічна одіссея ч. 2
Усі члени екіпажу космічного корабля знаходяться на борту, корабель успішно вийшов у відкритий космос. Команді вже час почати виконання своїх обов'язків: Людям — пілотувати корабель, Собаці — займатися навігацією, а Коту — досліджувати відкритий космос. Розподіли обов'язки членів екіпажу в методі r

2. Перевірка типу об'єкта

Але тут слід бути дуже обережними. Напишімо такий код:

Тварина звір = new Кіт ();
Вовк сірийВовк = (Вовк) звір;

Компілятор цей код пропустить, але під час виконання програми станеться помилка! JVM кине виняток:

Exception in thread "main" java.lang.ClassCastException: Кіт cannot be cast to Вовк

Посилання на об'єкт Кіт можна присвоїти тільки змінним, які мають тип батьківського класу для класу Кіт: ДомашняТварина, Тварина і Object.

Чому це так?

Річ у тім, що посилання на об'єкт використовується для того, щоб звертатися до методів і змінних цього об'єкта. Якщо зберегти у змінній типу Тварина посилання на об'єкт Кіт, то ніяких проблем не буде: тип Кіт завжди матиме змінну й методи типу Тварина, бо ж він їх успадкував!

Проте якби JVM дозволила зберегти посилання на об'єкт Кіт у змінній типу Вовк, могла б виникнути ситуація, коли для змінної сірийВовк викликано метод, відсутній в об'єкта Кіт, на який ця змінна посилається. Тому такі збереження заборонені.

У Java є спеціальний оператор instanceof, який дає змогу перевірити, чи можна зберегти об'єкт певного типу в змінній певного типу. Він має досить простий вигляд:

змінна instanceof Тип

Приклад:

Тварина звір = new Кіт ();
if (звір instanceof Вовк)
{
   Вовк сірийВовк = (Вовк) звір;
}

Такий код не спричинить помилок навіть під час виконання.

От іще кілька прикладів з описом ситуації:

Розширення типу Опис
Cow cow = new Whale();

Класичне розширення типу — оператор перетворення типу не потрібен. Тепер для об'єкта типу Whale можна викликати тільки методи, описані в класі Cow.

Компілятор дозволить викликати для змінної cow тільки методи її типу — класу Cow.

Звуження типу
Cow cow = new Whale();
if (cow instanceof Whale)
{
   Whale whale = (Whale) cow;
}
Класичне звуження типу: потрібно додати перевірку типу й оператор перетворення типу.
Змінна cow типу Cow зберігає посилання на об'єкт класу Whale.
Перевіряємо, що це насправді так, а потім виконуємо операцію перетворення (звуження) типу. Або як її ще називають —
type cast.

Cow cow = new Cow();
Whale whale = (Whale) cow; // exception
Вказівне звуження типу можна виконати навіть без перевірки типу об'єкта.
Причому, якщо у змінній cow зберігався об'єкт, який не належить до класу Whale, буде згенеровано виняток InvalidClassCastException.

18
Задача
Java Syntax Zero,  18 рівень4 лекція
Недоступна
Космічна одіссея ч. 3
Зробімо наш попередній приклад більш правильним і універсальним. Порядок, в якому астронавти додаються до списку astronauts, не завжди відомий. Щоб правильно розподілити завдання між членами екіпажу, потрібно визначити, ким саме є астронавт. Для цього в методі runWorkingProcess() перебери в циклі вс
18
Задача
Java Syntax Zero,  18 рівень4 лекція
Недоступна
Хижаки й травоїдні
Перед тобою 4 класи тварин — Cow, Lion, Wolf і Elephant. Корова (Cow) і слон (Elephant) є травоїдними, тому вони успадковуються від класу Herbivore. А лев (Lion) і вовк (Wolf) є хижаками, тому вони успадковуються від класу Predator. Своєю чергою класи Herbivore і Predator успадковано від класу Anima

3. Виклик оригінального методу: super

Іноді під час перевизначення потрібно лише трохи доповнити метод батьківського класу, а не замінити його на свій повністю.

Було б класно, якби під час виклику свого методу можна було викликати такий самий метод батьківського класу, а потім виконати ще й свій код. Або спочатку виконати свій код, а потім викликати метод батьківського класу.

І така можливість у Java є. Код для виклику методу саме батьківського класу має такий вигляд:

super.метод(параметри);

Приклади:

class МирнийЧас
{
   public double getPi()
   {
      return 3.14;
   }
}

class ВоєннийЧас extends МирнийЧас
{
   public double getPi()
   {
      return super.getPi()*2;  // 3.14*2
   }
}

У воєнний час число Pi може досягати значення 4, а в нашому випадку навіть 6! Це, звісно, жарт, але він демонструє, як усе це працює.

От іще кілька прикладів для кращого розуміння:

Код Опис
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.print("Це неправда: ");
      super.printName();
      System.out.println("Я — кит");
   }
}
Класи Cow і Whale
public static void main(String[] args)
{
   Whale whale = new Whale();
   whale.printAll();
}
На екран буде виведено напис:
Я — білий
Це неправда: Я — корова
Я — кит

Це дійсно непростий матеріал — щиро кажучи, одна з найскладніших тем в ООП. Проте його потрібно знати й розуміти.


18
Задача
Java Syntax Zero,  18 рівень4 лекція
Недоступна
Вихованці бувають різними
Клас Pet є батьківським класом для класів Cat і Dog. У ньому реалізовано метод printInfo(), який повідомляє, що цей об'єкт є вихованцем. У класах Cat і Dog потрібно перевизначити метод printInfo(), доповнивши його функціонал таким чином: спочатку виклич метод printInfo() батьківського класу; потім д