如何处理类层次结构
How to handle class hierarchy
我有一个关于如何处理这种类型的类层次结构的问题。等级制度与游戏有关,但我认为这已经足够概括游戏开发了。我想这种事情偶尔会出现,所以我很好奇可能的解决方案
我有一个叫做baseccharacter的基类来定义游戏中的角色。它包含了所有的基本属性,状态,效果持有者,事件等等。我的大多数游戏逻辑都是在baseccharacter的实体上操作的,必要时进行强制转换。
从那里我继承到一个Humanoid类,它添加必要的结构和方法来添加设备(武器,盔甲等)的角色,然后最后我有一个playablecrole类,继承自Humanoid并添加像当前经验,可配置的能力结构等。
所以类结构很简单:
BaseCharacter——>人形——> PlayableCharacter
这种结构对于定义玩家角色非常有效,尽管我可能会决定进一步完善结构。我必须能够在层次结构中添加"敌人"类。为了满足敌人的要求,我需要添加一些与打败敌人的经验/点数、战利品表等相关的数据结构/方法。
问题是,我在哪里添加这些结构?将它们添加到baseccharacter似乎是一个坏主意,因为我基本上说每个角色都有敌人实体所需的方法/数据结构。我考虑过开始一个单独的类流,最终看起来像这样:
BaseCharacter--->Humanoid--->PlayableCharacter
---->Enemy--->EnemyHumanoid
敌人从basecharter继承。EnemyHumanoid将添加与baseccharacter ->Humanoid继承相同的方法/数据结构集。这是可行的,但意味着我不能将EnemyHumanoid转换为Humanoid,尽管事实上EnemyHumanoid满足Humanoid的要求。这也增加了冗余,因为我要让这两个继承添加完全相同的对象/方法集。
则考虑使用一个名为EnemyInterface的单独类,并以这样的继承层次结构结束:
BaseCharacter----->Humanoid----->PlayableCharacter
| |
V V
Enemy EnemyHumanoid
Enemy和EnemyHumanoid都实现了EnemyInterface。然而,我现在失去了敌人<->敌人人形关系。我应该在这里使用多重继承吗?(敌人类人是从敌人和类人身上继承来的吗?)这被认为是不好的形态吗?有没有更合理的方法来做这件事?这里的例子相当简单,但是如果我最终把我的类层次结构分割得更多,它只会变得更复杂。
任何帮助都将是感激的
而不是重新安排你的类层次结构来解决这个特定的问题(参见StackUnderblow的答案,看看如何做到这一点),我建议你做一些研究基于组件的体系结构。从根本上说,比起使用一个类来描述使playablecarter独一无二的内容,你应该将一个组件(或一组组件)移植到某种基本容器上。
这种方法更加灵活,并且随着设计的发展更容易重构。例如,如果你有一个功能,某些敌人和人类都可以访问,那么你就必须将系统钩子添加到你的基类中,向不能使用该功能的敌人引入开销。这是描述一个简单问题的大量词汇,但随着游戏的发展,你会一次又一次地遇到这个问题。
下面是一个很好的关于我的建议的讨论。
Bheeshmar是对的,你正在通往地狱的道路上!
听起来你是在使用继承进行重用,而不是遵循LSP (http://en.wikipedia.org/wiki/Liskov_substitution_principle),这是通往地狱的道路。
我的一般建议是仅对is-a关系使用继承。也就是说,你可以用一种类型代替另一种类型。对于大多数解决方案,我更喜欢组合而不是继承,因为我发现它更简单。
在你的特殊情况下,为什么认为敌人不同于可玩角色?考虑在类层次结构之外设置EXP和Loot表,你可以将Humanoid传递给它并分别计算这些物品。
c++是一种多范式语言。你不必把自己局限于OO解决方案。
祝你好运!
这个怎么样?
BaseCharacter----->Humanoid----->PlayableCharacter
/
/
Enemy EnemyHumanoid
EnemyHumanoid可能只需要Humanoid的一些特性。
您正在尝试根据多个方面子类化您的baseccharacter类(错误,我不确定"aspect"在这里是正确的词,我不是英语母语者,对不起),即:
- 形式-人形/动物等
- 对齐-敌人/朋友/等
这总是会导致问题,正如您所观察到的:迟早您会想要创建应该从basecharter的多个子类继承的类(通常来自每个方面类别),例如。人形+敌人。在这种情况下,要么使用多重继承(由于实现问题,在c++中不推荐),要么需要重新设计代码。
通常最好的解决方案是根据前面确定的方面拆分对象。如。在一个baseccharacter对象中,你可以有两个指针,一个CharacterForm*和一个CharacterAlignment*。然后你可以独立地子类化CharacterForm(如HumanoidForm, AnimalForm等)和CharacterAlignment(如EnemyAlignment, FriendAlignment等),并根据需要组合它们。请注意,正如Dan O建议的那样,这种方法实际上是迈向基于组件的设计的第一步。
您需要做一些类似的每次您发现自己创建的子类是其基类的子类,在不同的意义上比以前的子类(例如。在创建人形和动物之后,你需要敌人->这显然是分类你的基本角色的不同方式)。经验法则是,每个类应该只根据一个方面成为子类。
要考虑的问题是是否需要将Humanoid
实例转换为BaseCharacter
实例。你可能会发现事实并非如此。你真的需要遍历所有人形角色的集合吗?
如果是,定义:
Humanoid
BaseCharacter->PlayableCharacter (contains Humanoid)
---->Enemy---->EnemyHumanoid (contains Humanoid)
[你可以考虑将敌人抽象为定义一个具体的EnemyNonhumanoid]
另一种方法是将Humanoid定义为一个接口,并在playablecharter和EnemyHumanoid上提供一个getHumanoid()方法,在每种情况下作为句柄实现。
这个怎么样?
BaseCharacter
IBehaviour
is接口
HumanoidBehaviour
是IBehaviour
的实现
BaseCharacter
包含IBehaviour
Enemy
继承BaseCharacter
并包含HumanoidBehaviour
PlayableCharacter
继承BaseCharacter
并包含HumanoidBehaviour
所以逻辑上我们将得到:Enemy
is-a BaseCharacter
和has-a行为HumanoidBehaviour
.
可能策略设计模式在这里会有所帮助还有一本有趣的书,里面有一个很好的例子)
- 如何重构类层次结构以避免菱形问题
- C++ 中模板化类型的类层次结构
- 为什么不同类型层次结构的指针之间的dynamic_cast定义得很好?
- 继承层次结构并将元素添加到向量
- C++ 类层次结构中的"对齐"是什么意思?
- 相同的层次结构,访问基类的受保护成员时的行为不同
- 类层次结构中的运算符重载
- 如何在层次结构中实现运算符使用?
- 反向层次结构中的可变参数模板参数
- 如何在继承层次结构中调用具有默认参数的构造函数?
- C++ 提升 - 包含类层次结构对象的类的序列化
- 在C++继承层次结构时提取实现者
- 在C++中将类实例添加到对象层次结构中的问题
- 确定大层次结构中基本指针的实际类型,无需dynamic_cast
- 在继承层次结构中复制和移动
- 如何在类层次结构中处理 CRTP
- 有没有更好的方法来处理将标识分配给层次结构中的类以供运行时使用
- 使用可重写的处理程序函数构建类层次结构
- 你能把一个异常继承层次结构包装到另一个吗?——或者,另一种干净的处理方式
- 如何处理类层次结构