1. Пегас
Розгляньмо детальніше третій принцип ООП — успадкування. Це дуже цікаве питання, з яким ви часто стикатиметеся. На думку необізнаних, програмування — це якась магія. Тому почнімо з отакої цікавої аналогії…
Припустімо, що ви — чарівник і хочете створити крилатого коня. Можна спробувати просто начаклувати такого пегаса. Але оскільки пегасів в природі не існує, це буде досить складно. Доведеться дуже багато робити з нуля. Куди простіше взяти коня й дочаклувати йому крила.
У програмуванні такий процес називається «успадкуванням». Припустімо, вам потрібно написати дуже складний клас. Писати з нуля довго, потім доведеться все тестувати й шукати помилки. То навіщо йти найскладнішим шляхом? Краще пошукати, а чи немає десь такого класу?
Припустімо, ви знайшли клас, який своїми методами реалізує 80 % потрібної вам функціональності. Що робити з ним далі? Ви можете просто скопіювати його код у свій клас. Однак такий спосіб має кілька мінусів:
- Знайдений клас уже може бути скомпільовано в байт-код, а доступу до його вихідного коду у вас немає.
- Вихідний код класу є, але ви працюєте в компанії, яку можуть засудити на пару мільярдів за використання навіть 6 рядків чужого коду. А потім вона засудить вас.
- Непотрібне дублювання великого обсягу коду. Крім того, автор чужого класу може знайти в ньому помилку й виправити її. А у вас ця помилка залишиться.
Є кращий спосіб, який не потребує легального доступу до коду вихідного класу. У мові Java можна просто оголосити потрібний клас батьківським для вашого класу. Ви отримаєте такий самий результат, наче ви додали код цього класу в код свого. У вашому класі з'являться всі дані та всі методи батьківського класу. Наприклад, можна зробити так: успадковуємо клас від «коня», додаємо «крила» й отримуємо «пегаса».
2. Спільний базовий клас
Успадкування можна також використовувати для інших цілей. Припустімо, у вас є десять класів, які дуже схожі між собою, мають багато однакових даних і методів. Ви можете створити спеціальний базовий клас, винести однакові дані (і методи, які з ними працюють) у цей базовий клас і оголосити ті десять класів його спадкоємцями. Тобто вказати в кожному класі, що у нього є батьківський клас — цей базовий клас.
Так само, як переваги абстракції розкриваються лише в поєднанні з інкапсуляцією, так і переваги успадкування значно збільшуються в разі використання поліморфізму. Однак про це ви дізнаєтеся трохи згодом. А сьогодні ми розглянемо кілька прикладів використання успадкування.
Шахові фігури
Припустімо, ми пишемо програму, що грає в шахи з користувачем, тож нам знадобляться класи для фігур. Які ж це будуть класи?
Якщо ви коли-небудь грали в шахи, то відповідь очевидна: Король, Ферзь, Слон, Кінь, Тура й Пішак.
До того ж у цих класах потрібно зберігати інформацію щодо кожної фігури. Наприклад, координати x і y, а також цінність фігури. Адже деякі фігури цінніші за інших.
Крім того, фігури здійснюють ходи по-різному, тож і поведінка класів має відрізнятися. Отак їх можна описати у вигляді класів:
|
|
|
|
|
|
Це дуже примітивний опис шахових фігур.
Спільний базовий клас
За допомогою успадкування цей код можна скоротити. Однакові методи й дані можна винести у спільний клас. Назвемо його ChessItem
. Об'єкти класу ChessItem
не має сенсу створювати, оскільки йому не відповідає жодна шахова фігура, але він дуже корисний:
|
|
|
|
||
|
|
|
Це чудовий спосіб спростити код схожих об'єктів. Найбільше переваг ми отримуємо, коли проєкт містить тисячі різних об'єктів і сотні класів. Тоді правильний підбір батьківських (базових) класів дає змогу не тільки істотно спростити логіку, але й скоротити код у десятки разів.
3. Успадкування класу — extends
То що ж потрібно, щоб успадкувати якийсь клас? Щоб успадкувати один клас від іншого, потрібно після оголошення нашого класу вказати ключове слово extends
та ім'я батьківського класу. Зазвичай це має приблизно такий вигляд:
class Нащадок extends Батько
Саме таку конструкцію слід написати під час оголошення класу «Нащадок». До речі, успадкування можливе тільки від одного класу.
На малюнку ми бачимо «корову», успадковану від «свині». «Свиню» успадковано від «курки», а «курку» — від «яйця». Тільки один батько! Таке успадкування не завжди логічне. Але якщо є тільки свиня, а дуже потрібна корова, програміст часто не здатний встояти перед спокусою зробити «корову» зі «свині».
У мові Java відсутнє множинне успадкування: не можна успадкувати клас від двох класів. У кожного класу може бути лише один батьківський клас. Якщо батьківський клас не вказано, ним вважається клас Object
.
Натомість у Java є множинне успадкування інтерфейсів. Це трохи знижує гостроту проблеми. Про інтерфейси ми поговоримо трохи згодом, а поки що продовжимо розгляд успадкування.
P.S.
Отут ви знайдете кілька історій про те, як часто доводиться робити з мухи свиню. І якими можуть бути наслідки:
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ