Ruby & Modularization. Существуют ли простые и понятные способы исключения || расширенных модулей / миксинов из классов? - PullRequest
3 голосов
/ 14 декабря 2011

Stackoverflowers!

Я недавно начал баловаться с Ruby, и у меня есть несколько вопросов.Сначала немного предыстории: я привык к наследованию C ++ и Java и всегда испытывал неприязнь к тому, как там работает наследование во многих игровых сценариях (например, в стиле roguelike).Главным образом из-за того, что трудно хорошо описать поведение.Например, в Java: (не то, чтобы я реализовал это таким образом, но это был лучший пример, который я мог предложить в короткие сроки.)

Actor extends GameObject
Creature extends Actor

FlyingCreature extends Creature
Dragon extends FlyingCreature

Humanoid extends Creature

... пока все хорошо,право?Но что, если я решил реализовать класс «Горгулья» (крылатый гуманоид)?Тогда он будет принадлежать как FlyingCreature, так и Humanoid - поэтому мне придется заключить в капсулу одну из черт, а затем рефакторировать ее или что-то в этом роде.

Идеальное решение - лично - было бы, если бы были какие-то эффективныеспособ извлечения уникальных атрибутов / функциональных возможностей в инкапсулированные объекты, а затем каждый GameObject представляет собой композицию из различных модульных компонентов, которые могут взаимодействовать друг с другом.(Без наследования, кроме событий, таких как Item: GameObject, Actor: GameObject, Tile: GameObject - если даже тогда).

Так что определенный GameObject (скажем, орк) может быть легко создан путем созданиядерево компонентов - что-то вроде этого, но более гибкое:

          [Actor]
[Organic]/  |    \[Persona] // Name, etc..
            |          \
       [Humanoid]      [Intelligence] // AI or PlayerController
            |
       [Inventory] // [ArrayList of items...]
            |
       [Equipment] // [Hash of :slot -> Item]

Но более важно: когда я начал изучать Ruby, я узнал о его возможностях метапрограммирования, его свободе во время выполнения благодаряотражение языка и возможности расширения / включения модулей.Поэтому я решил, что если бы я разделил определенные черты на модули (и удостоверился, что у них есть осторожные политики именования и тому подобное), то я мог бы позволить своим классам включать поведение в соответствии с контекстом и событиями.Например, допустим, у меня есть гном по имени Боб О'Копп, и он спотыкается о крошечного поросёнка-вампира, в то же время разговаривая в темной канализационной темнице.И, таким образом, он попадает в какую-то магическую лужу, которая его мутирует, давая ему милые сказочные крылья.Но так как гномы обычно не птичьи, его класс не обладает функциональностью полета.Но для этого случая это была бы действительная черта.Таким образом, я подумал, что «полет bob.extend» будет отличным решением проблемы.

Но что, если одна из черт является временной?Допустим, Боб О'Копп находит свиток, который вызывает магические крылья на спине на время действия заклинания ... Но.После долгих поисков я еще не нашел какой-либо хорошей информации о том, как убирать / расширять или исключать миксины после его применения - если это вообще возможно.И поскольку здесь много действительно умных и опытных программистов, я бы хотел официально попросить вас поделиться с вами великолепной проницательностью, о могучие бородатые оракулы!: -)

Итак ... несколько вопросов:

  • Бреду ли я, что хочу использовать миксин таким образом?
  • Есть ли у меня большой недостаток?не задумывались?
  • Можно ли вообще отозвать миксин после его применения?
  • Есть ли у вас какие-либо другие рекомендации для хорошего способа решения проблемы?(достаточно указать мне направление в виде некоторых ключевых слов)

С нетерпением ожидая любых ответов с ожиданием

Огромное спасибо заранее,

-Robocopulate

1 Ответ

5 голосов
/ 14 декабря 2011

Бреду ли я, что хочу использовать миксины таким образом?
Я не думаю, что вы бредите. Временные миксины звучат как отличный способ описать ваши цели.

Есть ли какой-то большой недостаток, о котором я не задумывался?
После небольшого размышления для меня это не очевидно, кроме (см. Следующий вопрос) & hellip;

Возможно ли отозвать миксин после нанесения? Не в неизмененном Ruby. Существуют различные предложения по добавлению unextend или аналогичные, но ни одно еще не было добавлено к официальному языку.

Однако есть библиотека Remix , которая предоставляет вам unextend и temp_include и более. Если вы собираетесь запустить где-нибудь этот Remix, вы можете использовать его.

Есть ли у вас какие-либо другие рекомендации относительно хорошего способа решения проблемы?
Вы всегда можете свернуть свою собственную систему наследования. : | Например, создайте функции модуля, которые принимают экземпляр для работы (возможно, с использованием instance_eval для нарушения его инкапсуляции и хранения пользовательских данных), а затем отслеживайте, доступен ли конкретный модуль.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...