Stackoverflowers!
我最近开始涉足Ruby,我有几个问题。首先是一些背景:我习惯于C ++和Java继承,并且总是不喜欢在很多与游戏相关的场景中继承如何工作(例如,roguelike)。主要是由于很难以良好的方式封装行为。例如,在Java中:(不是我以这种方式实现它,但这是我能在短时间内提出的最佳示例。)
Actor extends GameObject
Creature extends Actor
FlyingCreature extends Creature
Dragon extends FlyingCreature
Humanoid extends Creature
......到目前为止这么好,对吗?但是,如果我决定实施一个“Gargoyle”(有翼的人形)类怎么办?然后它将属于FlyingCreature和Humanoid - 所以我必须封装其中一个特征,然后重构它或其他东西。
理想的解决方案 - 个人 - 如果有一些有效的方法将独特的属性/功能提取到封装的对象中,然后让每个GameObject都是可以相互交互的不同模块化组件的组合。 (除了诸如Item:GameObject,Actor:GameObject,Tile:GameObject之类的可能性之外没有继承,即使那时)。
通过创建一个组件树,可以很容易地创建一个特定的GameObject(比如一个orc) - 粗略地像这样但更灵活:
[Actor]
[Organic]/ | \[Persona] // Name, etc..
| \
[Humanoid] [Intelligence] // AI or PlayerController
|
[Inventory] // [ArrayList of items...]
|
[Equipment] // [Hash of :slot -> Item]
但更重要的是:当我开始学习Ruby时,我了解了它的元编程能力,它是由于语言反射而产生的运行时自由,以及模块的扩展/包含功能。所以我认为,如果我将特定的特征划分为模块(并确保有仔细的命名策略等),那么我可以允许我的类根据上下文和事件包含行为。例如,假设我有一个名叫Bob O'Copp的矮人 - 他在一个黑暗的下水道地牢中探险时,他会骑着一只小小的吸血鬼仔猪。因此,他陷入了一些使他变异的神奇化学水坑 - 给他可爱的仙女翅膀。但由于矮人通常不是鸟类,他的班级不具备飞行功能。但对于这个例子,它将是一个有效的特征。因此,我认为“bob.extend Flight”将是一个很好的解决方案。
但是如果其中一个特征是暂时的呢?让我们说鲍勃奥科普找到一个卷轴,在法术持续时间内召唤魔法翅膀......但是。经过大量的谷歌搜索后,我还没有找到任何关于如何在应用后撤回/取消扩展或排除mixins的好信息 - 如果实际上可行的话。因为这里有很多非常聪明且经验丰富的程序员,所以我想正式恳请你赐予你一些伟大的洞察力,强大的大胡子啊! : - )
所以...几个问题:
热切期待任何回复预期
非常感谢提前,
-Robocopulate
答案 0 :(得分:5)
我是否因为想以这种方式使用mixins而妄想?
我不认为你是妄想症。临时混音听起来像是描述你的目标的巧妙方式。
我有没有想到的一些重大缺点?
经过一段时间的反思,这对我来说并不是那么明显,除了(见下一个问题)......
一旦应用,是否可以收回mixin?
不是未经修改的Ruby。添加unextend
或类似内容的提议有很多,但尚未添加到官方语言中。
但是,有Remix库,可为您提供unextend
和temp_include
以及更多内容。如果您打算在Remix可用的地方运行,可以使用它。
您是否有其他建议可以更好地解决问题?
您可以随时滚动自己的继承系统。 :|例如,创建模块函数,接受要操作的实例(可能使用instance_eval
来违反其封装并存储自定义数据),然后跟踪特定模块是否可用。