
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 IDEa, натисни 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()
тощо.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ