Animal
, що означає тварин, і створимо в ньому метод voice
- " голос ":
public class Animal {
public void voice() {
System.out.println("Голос!");
}
}
Хоча ми тільки почали писати програму, потенційна проблема тобі, швидше за все, видно: тварин у світі дуже багато, і всі «говорять» по-різному: кішки нявкають, качки крякають, змії шиплять. Наша мета проста: уникнути створення купи методів для голосування. Замість того, щоб створювати методи voiceCat()
для м'якання, voiceSnake()
для шипіння і т.д., ми хочемо, щоб при виклику методу voice()
змія шипіла, кішка мяукала, а собака гавкала. Ми легко досягнемо цього за допомогою механізму перевизначення методів (Override у Java) . Вікіпедія дає таке пояснення терміна «перевизначення»: Перевизначення методу (англ. Method overriding)) в об'єктно-орієнтованому програмуванні - одна з можливостей мови програмування, що дозволяє підкласу або дочірньому класу забезпечувати специфічну реалізацію методу, вже реалізованого в одному із суперкласів або батьківських класів. Воно, загалом, правильне. Перевизначення дозволяє взяти якийсь метод батьківського класу та написати у кожному класі-спадкоємці свою реалізацію цього методу. Нова реалізація замінить батьківську в дочірньому класі. Розглянемо, як це на прикладі. Створимо 4 класи-спадкоємці для нашого класу Animal
:
public class Bear extends Animal {
@Override
public void voice() {
System.out.println("Р-р-р!");
}
}
public class Cat extends Animal {
@Override
public void voice() {
System.out.println("Мяу!");
}
}
public class Dog extends Animal {
@Override
public void voice() {
System.out.println("Гав!");
}
}
public class Snake extends Animal {
@Override
public void voice() {
System.out.println("Ш-ш-ш!");
}
}
Невеликий лайфхак на майбутнє: щоб перевизначити методи батьківського класу, перейди в код класу-спадкоємця в Intellij IDE a, натисніть Ctrl+O та вибери в меню " Override methods... ". Звикай користуватись гарячими клавішами з початку, це прискорює написання програм! Щоб поставити потрібну нам поведінку, ми зробабо кілька речей:
- Створабо в кожному класі-спадкоємці метод з такою самою назвою, як і у методу батьківського класу.
-
Повідомабо компілятору, що ми не просто так назвали метод так само, як у класі-батьку: хочемо перевизначити його поведінку. Для цього «повідомлення» компілятор ми поставабо над методом анотацію @Override («перевизначений»).
Проставлена над методом анотація @Override повідомляє компілятору (та й програмістам, що читають твій код теж): «Все ок, це не помилка і не моя забудькуватість. Я пам'ятаю, що такий метод вже є, і хочу його перевизначити». - Написали потрібну нам реалізацію для кожного класу-нащадка. Змія при виклику
voice()
повинна шипіти, ведмідь - гарчати і т.д.
public class Main {
public static void main(String[] args) {
Animal animal1 = new Dog();
Animal animal2 = new Cat();
Animal animal3 = new Bear();
Animal animal4 = new Snake();
animal1.voice();
animal2.voice();
animal3.voice();
animal4.voice();
}
}
Висновок у консоль: Гав! Мяу! Р-р-р! Ш-ш-ш! Добре, все працює як треба! Ми створабо 4 змінні-посилання батьківського класу Animal
, і привласнабо їм 4 різних об'єкти класів-спадкоємців. У результаті кожен об'єкт поводиться по-своєму. Для кожного з класів-спадкоємців перевизначений метод voice()
замінив «рідний» метод voice()
із класу Animal
(який виводить у консоль просто «Голос!»). У перевизначення є низка обмежень:
-
У перевизначеного методу мають бути самі аргументи, як і в методу батька.
Якщо метод
voice
батьківського класу приймає на вхідString
, перевизначений метод у класі-нащадку теж повинен приймати на вхідString
, інакше компілятор видасть помилку:public class Animal { public void voice(String s) { System.out.println("Голос!" + s); } } public class Cat extends Animal { @Override//помилка! public void voice() { System.out.println("Мяу!"); } }
-
У перевизначеного методу має бути той самий тип значення, що повертається, що і у методу батька.
В іншому випадку ми отримаємо помилку компіляції:
public class Animal { public void voice() { System.out.println("Голос!"); } } public class Cat extends Animal { @Override public String voice() { //помилка! System.out.println("Мяу!"); return "Мяу!"; } }
-
Модифікатор доступу у перевизначеного методу також не може відрізнятись від «оригінального»:
public class Animal { public void voice() { System.out.println("Голос!"); } } public class Cat extends Animal { @Override private void voice() { //помилка! System.out.println("Мяу!"); } }
voice()
на всіх замість купи методів voiceDog()
, voiceCat()
і т.д.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ