1. Пегас
Давайте детальніше розберемо третій принцип ООП — наслідування. Це дуже цікава тема, якою ти будеш користуватись часто. Програмування, для тих, хто не розуміється, невідрізнене від магії. Тож почнемо з такої цікавої аналогії...;
Припустимо, що ти – чарівник і хочеш створити літаючого коня. З одного боку, ти міг би спробувати наколдувати пегаса. Але оскільки пегаси в природі не існують, це буде дуже непросто. Доведеться багато чого робити самостійно. Набагато простіше взяти коня і приколдувати йому крила.

В програмуванні цей процес називається «наслідування». Припустимо, тобі потрібно написати дуже складний клас. Писати з нуля довго, а потім ще довго все тестувати і шукати помилки. Для чого йти найскладнішим шляхом? Краще пошукати, а чи немає вже такого класу?
Припустимо, ти знайшов клас, який своїми методами реалізує 80% потрібної тобі функціональності. Що робити з ним далі? Ти можеш просто скопіювати його код у свій клас. Але у такого підходу є кілька мінусів:
- Знайдений клас вже може бути скомпільований у байт-код, а доступу до його вихідного коду у тебе немає.
- Вихідний код класу є, але ти працюєш у компанії, яку можуть засудити на пару мільярдів за використання навіть 6 рядків чужого коду. А потім вона засудить тебе.
- Непотрібне дублювання великого обсягу коду. До того ж, якщо автор чужого класу знайде в ньому помилки і виправить їх, у тебе ці помилки залишаться.
Є рішення елегантніше і без необхідності отримувати юридичний доступ до коду оригінального класу. У Java ти можеш просто оголосити той клас батьком твого класу. Це буде еквівалентно додаванню коду того класу в код твого. У твоєму класі з'являться всі дані та всі методи класу-батька. Наприклад, можна зробити так: наслідуємося від «коня», додаємо «крила» – отримуємо «пегаса»

2. Загальний базовий клас
Наслідування можна використовувати й для інших цілей. Наприклад, у тебе є десять класів, які дуже схожі, мають однакові дані та методи. Ти можеш створити спеціальний базовий клас, винести ці дані (і методи, що працюють з ними) в цей базовий клас і оголосити ті десять класів його спадкоємцями. Тобто вказати в кожному класі, що у нього є клас-батько — цей базовий клас.
Так само як переваги абстракції розкриваються тільки поряд з інкапсуляцією, так і переваги наслідування значно сильніші при використанні поліморфізму. Але про нього ти дізнаєшся трохи пізніше. Сьогодні ж ми розглянемо кілька прикладів використання наслідування.
Шахові фігури
Припустимо, ми пишемо програму, яка грає в шахи з користувачем, а значить, нам будуть потрібні класи для фігур. Що це будуть за класи?
Очевидна відповідь, якщо ти коли-небудь грав у шахи — Король, Ферзь, Слон, Кінь, Тура і Пішак.
Але у самих класах ще потрібно було б зберігати інформацію про кожну фігуру. Наприклад, координати x та y, а також цінність фігури. Адже деякі фігури цінніші за інших.
Крім того, фігури ходять по-різному, а значить і поведінка класів буде відрізнятися. Ось як можна було б описати їх у вигляді класів:
|
|
|
|
|
|
Це дуже примітивний опис шахових фігур.
Загальний базовий клас
А ось як можна було б скоротити код за допомогою наслідування. Ми могли б винести однакові методи і дані в загальний клас. Назвемо його ChessItem. Об'єкти класу ChessItem не має сенсу створювати, оскільки йому не відповідає жодна шахова фігура, але від нього було б багато користі:
|
|
|
|
||
|
|
|
Це чудовий спосіб спростити код схожих об'єктів. Особливо багато переваг ми отримуємо, коли в проєкті тисячі різноманітних об'єктів і сотні класів. Тоді правильно підібраними батьківськими (базовими) класами можна не лише суттєво спростити логіку, але й скоротити код у десятки разів.
3. Наслідування класу — extends
Так що ж треба, щоб успадковувати якийсь клас? Щоб успадковувати один клас від іншого, треба після оголошення нашого класу вказати ключове слово extends і написати ім'я батьківського класу. Виглядає це зазвичай приблизно так:
class Нащадок extends Батько
Саме таку конструкцію треба написати при оголошенні класу Нащадок. Успадковувати, до речі, можна лише від одного класу.

На малюнку ми бачимо «корову», успадковану від «свині». «Свиня» успадкована від «курки», «курка» від «яйця». Тільки один батько! Таке наслідування не завжди логічне. Але якщо є тільки свиня, а дуже потрібна корова, програміст часто не може втриматись перед бажанням зробити «корову» зі «свині».
У Java немає множинного наслідування: не можна успадковувати клас від двох класів. У кожного класу може бути тільки один клас-батько. Якщо клас-батько не вказаний, таким вважається клас Object.
Хоча в Java є множинне наслідування інтерфейсів. Це трохи знижує гостроту проблеми. Про інтерфейси ми поговоримо трохи пізніше, а поки давай продовжимо розбиратися з наслідуванням.
P.S.
Ось тобі кілька історій, про те, як часто доводиться робити зі звичайного об'єкта виняток. І що за це буває:
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ