Принципи ООП. Спадкування - FoxmindEd
💻 Activation Code: -30% на Start -30% на Start -30% на Start
Дізнатися більше
06.08.2022
6 хвилин перегляду

Принципи ООП. Спадкування

Сергій Немчинський
Принципи ООП. Спадкування

Спадкування – такий цікавий принцип, якого більшість сучасних програмістів взагалі намагається уникати. Що таке спадкування? За Вікіпедії це так: «абстрактний тип даних може успадковувати дані і функціональність деякого існуючого типу, сприяючи повторному використанню компонентів програмного забезпечення».

Перекладаю на людський: один клас може успадковувати інший клас, його поля і методи. Що значить наслідувати? Перевикористати. Після того, як клас оголошує себе спадкоємцем якогось класу, відповідні поля і методи з’являються в ньому автоматично. Цей принцип використовується в різних мовах. В Java це extenсe, в С ++ це двокрапка, в Ruby – трикутна дужках, і так далі.

Спадкування – це форма відносин між класами. Клас-спадкоємець використовує методи класу-предка, але не навпаки. Наприклад, клас «собака» є спадкоємцем класу «тварина», але «тварина» не буде наслідувати властивості класу «собака». Отже, спадкоємець – це більш вузький клас порівняно з предком.

При цьому успадкування називається словом extenсe, що означає “розширення”. Наприклад, ми вказуємо для класу «собака» поле «лапи» – а для класу «тварина» ми не можемо його використовувати, тому що у тварин часто зовсім немає лап, якщо це риба чи змія. Так що клас-спадкоємець може розширювати властивості базового класу, використовуючи його код.

Спадкування буває одиночне і множинне. Одиночне – це коли один або кілька класів успадковуються тільки від одного базового класу. Множинне спадкування – коли клас успадковується від декількох базових класів. Множинне спадкування є в багатьох мовах: ви можете перенести дані і \ або поведінку з інших класів. Але, наприклад, в Java множинне успадкування обмежено і можливо тільки від певного типу класів, наприклад, від інтерфейсу – так, інтерфейс це теж клас.

Через що у багатьох мовах обмежують множинне спадкування? Через ромбовидного успадкування. Коли два класи успадковують властивості одного базового, а потім якийсь четвертий клас успадковує другий і третій одночасно. Виходить плутанина: незрозуміло, яка реалізація повинна використовуватися. У деяких мовах, наприклад, Scala, це вирішили за допомогою порядку записи. Але це не така вже й важлива проблема: в кінці кінців, множинне спадкування не так вже необхідно, так що не таке велике це і обмеження.

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

Зараз багато початківці і не дуже програмісти вважають, що спадкування не треба використовувати ніколи, а треба використовувати делегування. На жаль, але таким чином вони стріляють собі в ногу. Припустимо, ви пишете кадрову систему. У вас є об’єкт типу «інженер», об’єкт типу «бухгалтер», об’єкт типу «менеджер». Якщо вони не є спадкоємцями від класу «person”, а просто три окремих класи, то щоб підрахувати кількість співробітників компанії, вам потрібно перебрати всі три списки. А коли додасться новий вид співробітників, вам потрібно не забути змінити весь код, який підраховує співробітників, і додати в нього четвертий список. Якщо ж знадобиться підрахувати, наприклад, тільки тих співробітників, які знаходяться в офісі, ви з розуму зійдете. У вас п’ять видів співробітників, які між собою не пов’язані між собою. Їх обробка займе купу часу, код виростає в рази. Це нерозумно.

Я бачив, як програмісти відмовлялися робити спадкування там, де воно буквально напрошувалося. Мій особистий принцип, який я і вам раджу: використовуйте спадкування, коли ці об’єкти дійсно виникають одна з одної. Нерозумно успадковувати непов’язаний об’єкт просто для того, щоб успадкувати властивості: тут краще застосувати делегування. Але в очевидних випадках, відмовившись від спадкування, ви вистрілите собі в ногу і створите масу проблем на рівному місці.

Так, я розумію, що з багатьма фреймворками виникають питання, як правильно Меппен, як правильно працювати з деревами успадкування, що робити, і так далі. Але якщо ви знайомі з GoF-овскими паттернами, згадайте: майже всі вони використовують успадкування і поліформізм. А справжній поліморфізм, як ви здогадуєтеся, без успадкування практично не працює. Тому, якщо ви повністю відмовляєтеся від спадкування, ви відмовляєтеся від всієї потужності ООП і відкочується в кам’яний вік, в процедурне програмування. Спадкування – це одна з головних сил ООП, і відмовлятися від неї нерозумно.

Сергій Немчинський
CEO FOXMINDED
Додати коментар

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

Зберегти моє ім'я, імейл та адресу сайту у цьому браузері для майбутніх коментарів