Я считаю, что было бы здорово, что и тролль, и оборотень унаследовали свои атрибуты от врага и переписали некоторые из них.
К сожалению, такой подход к полиморфизму, популярный в 90-х годах, на практике оказался плохой идеей. Представьте, что вы добавили «волка» в список врагов - ну, он разделяет некоторые атрибуты с оборотнем, поэтому вы хотите объединить их в общий базовый класс, например. 'WolfLike. Теперь вы добавляете «Человека» в список врагов, но оборотни иногда являются людьми, поэтому они также имеют общие черты, такие как ходьба на двух ногах, способность говорить и т. Д. Вы создаете общую базу «Гуманоидов» для людей и оборотней? и нужно ли вам тогда останавливать оборотней, происходящих от WolfLike? Или вы умножаете наследование от обоих - в этом случае какой атрибут имеет приоритет, когда что-то в Humanoid конфликтует с чем-то в WolfLike?
Проблема в том, что попытка моделировать реальный мир как дерево классов неэффективна. Возьмите любые 3 вещи, и вы, вероятно, найдете 4 различных способа разделить их поведение на общие и не общие. Вот почему многие вместо этого обратились к модульной или основанной на компонентах модели, где объект состоит из нескольких меньших объектов, составляющих единое целое, и меньшие объекты можно поменять местами или изменить, чтобы создать желаемое поведение. Здесь у вас может быть только 1 класс Enemy, и он содержит подобъекты или компоненты для того, как он ходит (например, Bipedal против Quadrupedal), его методы атаки (например, укус, коготь, оружие, кулак), его кожа (зеленый для троллей, пушистых, для оборотней и волков) и т. д.
Это все еще полностью объектно-ориентированный, но понятие того, что является полезным объектом, отличается от того, что обычно преподавалось в учебниках. Вместо того, чтобы иметь большое дерево наследования различных абстрактных классов и несколько конкретных классов на кончиках дерева, у вас обычно есть только 1 конкретный класс, представляющий абстрактное понятие (например, «враг»), но который содержит более конкретные классы, представляющие более абстрактные понятия (например, приступы, тип кожи). Иногда эти вторые классы лучше всего реализовать через 1 уровень наследования (например, базовый класс Attack и несколько производных классов для конкретных атак), но глубокое дерево наследования пропало.
Но, может быть, занятия слишком тяжелы, чтобы быть практичными, я не знаю ...
В большинстве современных языков классы не «тяжелые». Это просто еще один способ написания кода, и они обычно просто оборачивают процедурный подход, который вы бы в любом случае написали, за исключением более простого синтаксиса. Но во что бы то ни стало, не пишите класс, который будет выполнять функция. Классы по сути не лучше, только когда они делают код более простым в управлении или понимании.