Урок №162. Базове спадкування

  Юрій  | 

  Оновл. 26 Вер 2021  | 

 208

Тепер, коли ми вже поговорили про спадкування в абстрактному ключі, давайте поговоримо про те, як це використовується в мові C++ на практиці.

Спадкування в С++

Спадкування в C++ відбувається між класами і має тип відносин «є». Клас, від якого успадковують, називається батьківським (або “базовим”, “суперкласом”), а клас, який успадковує, називається дочірнім (або “похідним”, “підкласом”).

У діаграмі, представленій вище, Фрукт є батьківським класом, а Яблуко і Банан — дочірніми класами.

У цій діаграмі Трикутник є дочірнім класом (батько — Фігура) і батьківським (для Правильного трикутника) одночасно.

Дочірній клас успадковує як поведінку (методи), так і властивості (змінні-члени) від батька (з урахуванням деяких обмежень доступу, які ми розглянемо трохи пізніше). Ці методи і змінні стають членами дочірнього класу.

Оскільки дочірні класи є повноцінними класами, то вони можуть (звичайно) мати і свої власні члени. Зараз ми це все розглянемо детально.

Клас Human

Ось простий клас Human для представлення Людини:

У цьому класі ми визначили тільки ті члени, які є загальними для всіх об’єктів цього класу. Кожна Людина (незалежно від статі, професії тощо) має Ім’я та Вік.

Зверніть увагу, у вищенаведеному прикладі ми зробили всі змінні-члени і методи класу відкритими. Це зроблено заради простоти прикладу. Зазвичай змінні-члени потрібно робити private. Про засоби контролю доступу та про те, як це працює в спадкуванні, ми поговоримо на відповідних уроках.

Клас BasketballPlayer

Припустимо, що нам потрібно написати програму, яка відслідковуватиме інформацію про баскетболістів. Ми можемо зберігати середній рівень гри баскетболіста і кількість очок.

Ось наш незавершений клас BasketballPlayer:

Також нам потрібно знати Ім’я та Вік баскетболіста, а ця інформація вже у нас є: вона зберігається в класі Human.

У нас є три варіанти додавання Імені та Віку в BasketballPlayer:

   Додати Ім’я та Вік в клас BasketballPlayer безпосередньо в якості членів. Це поганий варіант, тому що відбудеться дублювання коду, який вже існує в класі Human. Будь-які оновлення в Human також повинні бути продубльовані і в BasketballPlayer.

   Додати клас Human в якості члену в клас BasketballPlayer, використовуючи композицію. Але виникає питання: “Чи може BasketballPlayer мати Human?”. Ні, це некоректно.

   Зробити так, щоб BasketballPlayer успадкував необхідні атрибути від Human. Пам’ятайте, що тип відносин в спадкуванні — «є». Чи є BasketballPlayer Human-ом (тобто Людиною)? Звісно! Тому наш вибір — спадкування.

Робимо клас BasketballPlayer дочірнім

Щоб клас BasketballPlayer успадкував інформацію від класу Human, нам потрібно після оголошення BasketballPlayer (class BasketballPlayer) використати двокрапку, ключове слово public і ім’я класу, від якого ми хочемо успадкувати. Це називається відкритим успадкуванням:

Проілюструємо:

Коли BasketballPlayer наслідує властивості класу Human, то BasketballPlayer набуває методи і змінні-члени класу Human. Крім того, BasketballPlayer має ще два своїх власних члени: m_gameAverage і m_points. В цьому є сенс, тому що ці властивості специфічні тільки для BasketballPlayer, а не для кожного Human-а.

Таким чином, об’єкти BasketballPlayer матимуть 4 члени:

   m_gameAverage і m_points від BasketballPlayer;

   m_name і m_age від Human.

Повний код програми:

Результат виконання програми:

Anton

Це працює, тому що anton є об’єктом класу BasketballPlayer, а всі об’єкти класу BasketballPlayer мають змінну-член m_name і метод getName(), успадковані від класу Human.

Дочірній клас Employee

Тепер напишемо ще один клас, який також успадковуватиме властивості Human. Наприклад, клас Employee (Працівник). Працівник «є» Людиною, тому використовувати спадкування тут доречно:

Працівник успадковує m_name і m_age від Human (а також два методи) і має ще дві власні змінні-члени і один метод. Зверніть увагу, метод printNameAndWage() використовує змінні як з класу, до якого належить (Employee::m_wage), так і з батьківського класу (Human::m_name).

Проілюструємо:

Зверніть увагу, класи Employee і BasketballPlayer не мають прямих відносин, хоча обидва успадковують властивості класу Human.

Ось повний код:

Результат виконання програми:

Ivan: 350

“Ланцюжок” спадкувань

Можна наслідувати від класу, який сам успадковує від іншого класу. При цьому нічого примітного або чого-небудь особливого не відбувається — все аналогічно тому, що ми розглянули вище. Наприклад, напишемо клас Supervisor (Супервайзер). Супервайзер — це Працівник, який “є” Людиною. Ми вже написали клас Employee, тому будемо його використовувати в якості батьківського класу:

Дивимося:

Всі об’єкти Supervisor успадковують методи і змінні від Employee і Human, а також мають свою власну змінну-член m_nOverseesIDs.

Побудувавши такі “ланцюжки” наслідувань, ми можемо створити набір повторно використовуваних класів, які матимуть загальні властивості зверху і ставатимуть все більш специфічними на кожному наступному рівні спадкування.

Чому спадкування є корисним?

Використання спадкування означає, що нам не потрібно перевизначати інформацію з батьківських класів в дочірніх. Ми автоматично отримуємо методи і змінні-члени суперкласу через спадкування, а потім просто додаємо специфічні методи або змінні-члени, які хочемо. Це не тільки економить час і зусилля, але також є дуже ефективним: якщо ми коли-небудь оновимо або змінимо базовий клас (наприклад, додамо нові функції або виправимо помилку), то всі наші похідні класи автоматично успадкують ці зміни!

Наприклад, якщо ми додамо новий метод в Human, то Employee і Supervisor автоматично отримають доступ до нього. Якщо ми додамо нову змінну в Employee, Supervisor також отримає доступ до неї. Це дозволяє створювати нові класи більш простим, інтуїтивно зрозумілим способом!

Висновки

Спадкування дозволяє повторно використовувати класи шляхом наслідування членів цих класів іншими класами. На наступних уроках ми розберемося детально, як це все працює.

Оцінити статтю:

1 Зірка2 Зірки3 Зірки4 Зірки5 Зірок (4 оцінок, середня: 5,00 з 5)
Loading...

Залишити відповідь

Ваш E-mail не буде опублікований. Обов'язкові поля відмічені *