1. Перетворення типів
Змінні вказівних типів (класів) теж можна перетворювати на різні типи. Однак це діє лише в межах однієї ієрархії типів. Розгляньмо простий приклад. Припустімо, у нас є така ієрархія класів: класи, показані нижче, успадковуються від класів, показаних вище.
Перетворення вказівних типів, так само як і примітивних, поділяються на розширення й звуження.
Ми бачимо, що клас Кіт успадковано від класу ДомашняТварина, а клас ДомашняТварина своєю чергою успадковано від класу Тварина.
Напишімо такий код:
Тварина котик = new Кіт();
Це перетворення є розширенням типу: його ще називають неявним. Ми розширили посилання котик, і тепер воно посилається на об'єкт типу Кіт. У разі такого перетворення ми не зможемо через посилання котик викликати методи, які має клас Кіт, але яких не має клас Тварина.
Перетворення-звуження (або явне перетворення) відбувається у зворотному напрямку:
Кіт киця = (Кіт) котик;
Ми явно вказали, що хочемо перетворити посилання, що зберігається у змінній котик (типу Тварина), на тип Кіт.
2. Перевірка типу об'єкта
Але тут слід бути дуже обережними. Напишімо такий код:
Тварина звір = new Кіт ();
Вовк сірийВовк = (Вовк) звір;
Компілятор цей код пропустить, але під час виконання програми станеться помилка! JVM кине виняток:
Exception in thread "main" java.lang.ClassCastException: Кіт cannot be cast to Вовк
Посилання на об'єкт Кіт можна присвоїти тільки змінним, які мають тип батьківського класу для класу Кіт: ДомашняТварина, Тварина і Object.
Чому це так?
Річ у тім, що посилання на об'єкт використовується для того, щоб звертатися до методів і змінних цього об'єкта. Якщо зберегти у змінній типу Тварина посилання на об'єкт Кіт, то ніяких проблем не буде: тип Кіт завжди матиме змінну й методи типу Тварина, бо ж він їх успадкував!
Проте якби JVM дозволила зберегти посилання на об'єкт Кіт у змінній типу Вовк, могла б виникнути ситуація, коли для змінної сірийВовк викликано метод, відсутній в об'єкта Кіт, на який ця змінна посилається. Тому такі збереження заборонені.
У Java є спеціальний оператор instanceof
, який дає змогу перевірити, чи можна зберегти об'єкт певного типу в змінній певного типу. Він має досить простий вигляд:
змінна instanceof Тип
Приклад:
Тварина звір = new Кіт ();
if (звір instanceof Вовк)
{
Вовк сірийВовк = (Вовк) звір;
}
Такий код не спричинить помилок навіть під час виконання.
От іще кілька прикладів з описом ситуації:
Розширення типу | Опис |
---|---|
|
Класичне розширення типу — оператор перетворення типу не потрібен. Тепер для об'єкта типу Компілятор дозволить викликати для змінної |
Звуження типу | |
|
Класичне звуження типу: потрібно додати перевірку типу й оператор перетворення типу. Змінна cow типу Cow зберігає посилання на об'єкт класу Whale . Перевіряємо, що це насправді так, а потім виконуємо операцію перетворення (звуження) типу. Або як її ще називають — type cast.
|
|
Вказівне звуження типу можна виконати навіть без перевірки типу об'єкта. Причому, якщо у змінній cow зберігався об'єкт, який не належить до класу Whale , буде згенеровано виняток InvalidClassCastException .
|
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! Це, звісно, жарт, але він демонструє, як усе це працює.
От іще кілька прикладів для кращого розуміння:
Код | Опис |
---|---|
|
Класи Cow і Whale
|
|
На екран буде виведено напис:
|
Це дійсно непростий матеріал — щиро кажучи, одна з найскладніших тем в ООП. Проте його потрібно знати й розуміти.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ