Я вважаю, було б здорово, що і троль, і перевертень успадкували свої атрибути від ворога і перекреслили деякі з них.
На жаль, такий підхід до поліморфізму, популярний у 90-х, показав себе поганою ідеєю на практиці. Уявіть, що ви додаєте "вовка" до списку ворога - добре, він поділяє деякі атрибути з перевертнем, тому ви хочете об'єднати їх у спільний базовий клас, наприклад. 'WolfLike'. Тепер ви додаєте "Людину" до списку ворога, але перевертні іноді є людьми, тому вони також діляться атрибутами, наприклад, ходіння по 2 ногах, вміння розмовляти тощо. , і чи потрібно вам тоді зупинити перевертнів, що походять від WolfLike? Або ви примножуєте спадщину з обох - у такому випадку, який атрибут має перевагу, коли щось у Гуманоїді зіштовхується з чимось у WolfLike?
Проблема полягає в тому, що намагатися моделювати реальний світ як дерево класів неефективно. Візьміть будь-які 3 речі, і, ймовірно, ви зможете знайти 4 різних способи розподілити їх поведінку на загальну та не поділену. Ось чому багато хто звернувся замість цього до модульної або компонентної моделі, де об'єкт складається з декількох менших об'єктів, які складають ціле, а більш дрібні об'єкти можна поміняти або змінити, щоб скласти потрібну поведінку. Тут у вас може бути лише 1 клас Ворог, і він містить під-об'єкти або компоненти для того, як він ходить (наприклад, двоногий проти чотириногих), способи нападу (наприклад, укус, кігтьок, зброя, кулак), шкіру (зелений для тролів, пухнастих для перевертнів та вовків) тощо.
Це все ще цілком об'єктно-орієнтоване, але поняття того, що є корисним об'єктом, відрізняється від того, що зазвичай викладалося в підручниках. Замість того, щоб мати велике дерево спадкування різних абстрактних класів та кілька конкретних класів на кінчиках дерева, у вас зазвичай є лише 1 конкретний клас, що представляє абстрактне поняття (наприклад, «ворог»), але який містить більш конкретні класи, що представляють більш абстрактні поняття (наприклад, напади, тип шкіри). Іноді ці другі класи можуть бути найкраще реалізовані через 1 рівень успадкування (наприклад, базовий клас Attack та кілька похідних класів для конкретних атак), але глибоке дерево спадкування відсутнє.
Але, можливо, заняття занадто важкі, щоб бути практичними, я не знаю ...
У більшості сучасних мов заняття не є «важкими». Вони просто інший спосіб написання коду, і вони, як правило, просто обробляють процедурний підхід, який би ви написали в будь-якому випадку, за винятком більш легкого синтаксису. Але в будь-якому разі не пишіть клас, де буде виконуватися функція. Заняття не є суттєво кращими, лише там, де вони полегшують управління чи розуміння.