Предположим, у вас есть следующее:
+--------+ +------+
| Animal | | Food |
+-+------+ +----+-+
^ ^
| |
| |
+------+ +-------+
| Deer | | Grass |
+------+ +-------+
Deer
наследует от Animal
и Grass
наследует от Food
.
Все идет нормально. Animal
объекты могут есть Food
объекты.
Теперь давайте немного перемешаем. Давайте добавим, Lion
который наследуется от Animal
.
+--------+ +------+
| Animal | | Food |
+-+-----++ +----+-+
^ ^ ^
| | |
| | |
+------+ +------+ +-------+
| Deer | | Lion | | Grass |
+------+ +------+ +-------+
Теперь у нас есть проблема, потому что Lion
может есть и то, Deer
и другое Grass
, но Deer
это не Food
так Animal
.
Как решить эту проблему без использования множественного наследования и объектно-ориентированного проектирования?
К вашему сведению: я использовал http://www.asciiflow.com для создания диаграмм ASCII.
object-oriented
object-oriented-design
Майкл Ирей
источник
источник
IHuntable
, Овцы и КоровыIHerdable
(управляются человеком), а Лион реализует только IAnimal, что не подразумевает какой-либо из этих интерфейсов. AOE3 поддерживает запрос набора интерфейсов, поддерживаемых конкретным объектом (аналогичноinstanceof
), что позволяет программе запрашивать его возможности.Ответы:
ИС отношения = наследование
Лев это животное
ИМЕЕТ отношения = Состав
У машины есть колесо
МОЖЕТ СДЕЛАТЬ отношения = Интерфейсы
Я могу есть
источник
ICanBeEaten
илиIEdible
ОО - это просто метафора, которая образует себя после реального мира. Но метафоры только заходят так далеко.
Обычно нет правильного способа моделировать что-то в ОО. Существует правильный способ сделать это для конкретной проблемы в определенном домене, и вы не должны ожидать, что он будет работать хорошо, если вы измените свою проблему, даже если объекты домена одинаковы.
Я думаю, что это распространенное заблуждение большинства комп. Eng. студенты в первые годы. OO - это не универсальное решение, а просто достойный инструмент для решения каких-то проблем, которые могут достаточно хорошо моделировать ваш домен.
Я не ответил на вопрос именно потому, что нам не хватает информации о домене. Но с учетом вышесказанного вы можете разработать что-то, что соответствует вашим потребностям.
источник
Вы хотите далее разбивать животных на подклассы (или, по крайней мере, насколько это имеет смысл для того, что вы делаете). Учитывая, что вы работаете с тем, что похоже на основных животных и два вида пищи (растения и мясо), имеет смысл использовать плотоядных и травоядных животных для дальнейшего определения животного и поддержания их раздельной. Вот что я нарисовал для тебя.
Как вы можете видеть, они оба представляют метод питания, но то, что они едят, меняется. Лев теперь может убить оленя, олень может умереть и вернуть DeerMeat, и на оригинальный вопрос ОП, как разрешить льву есть оленя, но не траву, дан ответ без создания целой экосистемы.
Конечно, это становится очень интересным очень быстро, потому что Оленя также можно считать типом мяса, но для простоты я бы создал метод kill () под deer, который возвращает мясо оленя, и поместил бы его как конкретный класс, расширяющий мясо.
источник
Eat(Plant p)
иEat(Meat m)
оба нарушают ЛСП.Мой дизайн будет выглядеть так:
Поскольку животные реализуют IMeat, а Олень - это (Травоядное) животное, Лев, который является (Плотоядным) животным, которое может есть IMeat, может также есть и оленей.
Олень - это травоядное животное, поэтому он может есть траву, потому что в нем реализован овощ.
Плотоядные не могут есть IVegeable, а травоядные не могут есть IMeat.
источник
Какая пища может есть животное, на самом деле не образует иерархию, в этом случае природа непростительно не соответствовала простому объектно-ориентированному моделированию (заметьте, что даже если бы это было так, животное должно было бы наследовать от пищи, поскольку это пища).
Знание того, какую пищу может съесть животное, не может полностью жить ни с одним из классов, поэтому простого обращения к какому-либо члену пищевой иерархии может быть недостаточно, чтобы сказать вам, что вы можете есть.
Это отношения многие ко многим. Это означает, что каждый раз, когда вы добавляете животное, вам нужно выяснить, что оно может съесть, и каждый раз, когда вы добавляете пищу, вам нужно выяснить, что можно съесть. Будет ли использоваться дополнительная структура, зависит от того, каких животных и продуктов вы моделируете.
Множественное наследование тоже не очень хорошо решает эту проблему. Вам нужен какой-то набор вещей, которые животное может съесть, или животных, которые могут есть пищу.
источник
Я подойду к проблеме с другой стороны: ООП - это поведение. В вашем случае,
Grass
есть ли какое-то поведение, чтобы быть ребенкомFood
? Так что в вашем случае не будетGrass
класса, или, по крайней мере, он не будет наследоваться отFood
. Кроме того, если вам необходимо установить, кто может есть что во время компиляции, сомнительно, что вам нужнаAnimal
абстракция. Кроме того, нередко можно увидеть плотоядных животных, поедающих траву , хотя и не для пропитания.Так что я бы разработал это как (не собираясь беспокоиться об искусстве ASCI):
IEdible
со свойствомType
, которое представляет собой перечисление мяса, растений, туш и т. д. (это не будет часто меняться и не будет иметь какого-либо особого поведения, поэтому нет необходимости моделировать его как класс hiearchy).Animal
с методамиCanEat(IEdible food)
иEat(IEdible food)
, которые логичны. Затем определенные животные могут проверять всякий раз, когда они могут съесть данную пищу в определенных обстоятельствах, а затем съесть эту еду, чтобы получить средства к существованию / сделать что-то еще. Кроме того, я бы смоделировал классы «Плотоядное животное» , «Травоядное животное», «Всеядное животное» как образец стратегии , а не как часть иерархии животных.источник
TL; DR: дизайн или модель с контекстом.
Я думаю, что ваш вопрос сложен, потому что в нем отсутствует контекст той проблемы, которую вы пытаетесь решить. У вас есть некоторые модели и некоторые отношения, но вам не хватает структуры, в которой он должен работать. Без контекста моделирование и метафоры не работают хорошо, оставляя дверь открытой для множественных интерпретаций.
Я думаю, что более продуктивно сосредоточиться на том, как будут использоваться данные. Если у вас есть схема использования данных, вам будет легче вернуться к тому, какими должны быть модели и отношения.
Например, более подробные требования потребуют различных объектных отношений:
Animals
eat
нон-Food
лайкGastroliths
Chocolate
какPoison
дляDogs
, но не дляHumans
Если мы начнем с упражнения о том, как смоделировать простые отношения, представленные, интерфейс питания может быть лучшим; и если это общая сумма отношений в системе, то ваш штраф. Однако лишь несколько дополнительных требований или отношений могут значительно повлиять на модели и отношения, которые работали в более простом случае.
источник
Подход ECS к составному наследованию:
псевдокод:
Nature
этоsystem
цикл, проходящий через эти сущности, ищущий какие компоненты они имеют через обобщенную функцию запроса.Nature
заставит сущности, жаждущие мяса, атаковать других сущностей, которые используют мясо в качестве пищи, используя свое оружие, если только они не имеют сродства с этой сущностью. Если атака будет успешной, сущность будет питаться своей жертвой, после чего жертва превратится в труп, лишенный мяса.Nature
приведет к тому, что сущности, жаждущие растений, будут питаться сущностями, у которых растение является пищей при условии, что они существуют.Возможно, мы хотим расширить,
Grass
чтобы иметь потребность в солнечном свете и воде, и мы хотим ввести солнечный свет и воду в наш мир. ИGrass
все же не может искать их напрямую, так как не имеетmobility
.Animals
может также нуждаться в воде, но может активно искать это, так как у них естьmobility
. Довольно легко продолжать расширять и изменять эту модель без каскадных поломок всего проекта, поскольку мы просто добавляем новые компоненты и расширяем поведение наших систем (или количества систем).источник
Как и большинство вещей, это зависит .
Это зависит от того, что вы видите «этой проблемой».
Если вы спрашиваете об общей проблеме реализации, ответ будет зависеть от возможностей вашей среды. Интерфейсы IFood и IAnimal могут работать с подклассом EdibleAnimal, реализующим оба интерфейса. Если ваша среда не поддерживает интерфейсы, просто заставьте Animal наследовать от Food.
Если вы спрашиваете об этой конкретной проблеме дизайна, просто заставьте Animal наследовать от Food. Это самая простая вещь, которая могла бы работать.
Если вы спрашиваете об этих концепциях дизайна, ответ сильно зависит от того, что вы собираетесь делать с моделью. Если это видеоигра «собачья еда» или даже приложение для отслеживания графиков кормления в зоопарке, этого может быть достаточно для работы. Если это для концептуальной модели поведения животных, это, вероятно, немного поверхностно.
источник
Наследование должно использоваться для чего-то, что всегда является чем-то другим, и не может измениться. Трава не всегда еда. Например, я не ем траву.
Трава играет роль корма для определенных животных.
источник
Вы только что столкнулись с основным ограничением ОО.
ОО хорошо работает с иерархическими структурами. Но как только вы уходите от строгой иерархии, абстракция работает не так хорошо.
Я знаю все о композициях метаморфоз и т. Д., Которые используются для преодоления этих ограничений, но они неуклюжи и, что более важно, ведут к неясному и трудному для понимания коду.
Реляционные базы данных были придуманы в первую очередь для того, чтобы избежать ограничений строгих иерархических структур.
Например, трава может быть строительным материалом, сырьем для бумаги, материалом для одежды, сорняком или культурой.
Олень может быть домашним животным, домашним скотом, животным в зоопарке или охраняемым видом.
Лев также может быть животным в зоопарке или охраняемым видом.
Жизнь не проста.
источник
Какая проблема? Что делает эта система?Пока вы не ответите, я понятия не имею, какие классы могут потребоваться. Вы пытаетесь смоделировать экологию с хищниками, травоядными и растениями, проецируя популяции видов в будущее? Вы пытаетесь заставить компьютер играть 20 вопросов?
Начать проектирование - пустая трата времени, прежде чем будут определены какие-либо варианты использования. Я видел, как это дошло до нелепых крайностей, когда команда из десяти человек начала выпускать оригинальную модель авиакомпании с использованием программного обеспечения через изображения. Они работали два года в модельном бизнесе, не задумываясь о реальных проблемах бизнеса. Наконец клиент устал ждать и попросил команду решить актуальную проблему. Все это моделирование было совершенно бесполезным.
источник