【问题标题】:Coping with single inheritance in a game应对游戏中的单一继承
【发布时间】:2015-02-12 10:29:44
【问题描述】:

我对 2d 游戏有一个简单的概念。想象一下最终幻想/ D&D设置。我在 C# 中工作,但它更多的是一般的单继承 OO 问题。我只是假设有一个方案,您可以实现许多接口但只继承一个类。

游戏中存在三种类型的实体:玩家、村民和敌人。澄清一下,可能有多个玩家 (AI),因为有些人可能会加入。

对于操作: 玩家可以进行战斗和对话。村民只能使用对话。敌人只能战斗。

对于状态: 所有实体在地图上都有一个位置。 战斗人员总是有当前生命值、最大生命值等。 对话实体总是有一些特定的问候文本、对话选项等。

玩家、村民和敌人将是我的具体类。看来我想要 2 个界面:Combat 和 Dialogue,处理所有动作。到目前为止一切顺利 - 然而,这些实体以一种对单一继承有问题的方式共享状态。根据我的设计,我似乎想要

  • 在地图上具有位置的抽象实体类
  • 抽象类 AbstractCombatant 和其他 AbstractDialogue 都继承自 Entity。例如,AbstractCombatant 具有健康、设备等状态。

这里的问题是 Player 想要继承 Combatant 和 Dialogue 抽象类。使用单一继承,我不能。如果可以的话,我会遇到 Entity 类的菱形继承问题。即使我只是让我的具体类继承 Entity,这将是另一个多重继承问题。当然,如果我完全将实体部分排除在等式之外,只是将实体分别映射到位置,我仍然会遇到 Player 从两个类继承的问题。

我想不出一个不重复实现的单继承设计。为这种情况设置类/接口层次结构的最佳方法是什么?

【问题讨论】:

  • 组合、混合而不是继承怎么样
  • 听起来像 AbstractCombatant 和 AbstractDialogue 应该是接口。然后你的具体类将从 Entity 继承并实现他们需要的接口。
  • 同意^(以上2 cmets)。你总是希望你的敌人永远没有对话选项吗?在我看来,如果你想在未来某个时候在游戏中放置一个老板,这会改变吗?
  • ^ 添加到上述内容:然后您可以创建一个额外的具体 Boss 类,该类将从 Enemy 继承并在其上添加 AbstractDialogue。也许吧。

标签: oop inheritance multiple-inheritance


【解决方案1】:

您很自然地希望为您的问题领域/业务领域中的每个概念(玩家、敌人、村民等)设置一个类。当这些概念具有共同特征时,问题自然会出现。考虑这个例子:

class House : IHouse
{
    public int StreetNumber { get; }
}

class Boat : IBoat
{
    public double SpeedKnots { get; }
}

class HouseBoat : House, Boat  // does not compile
{
}

解决此问题的最简单方法是使用聚合。

平衡

保留对所有底层概念的引用并实现适当的接口以提供所有必需的功能。

class HouseBoat : IHouse, IBoat // implementing both interfaces is ok
{
    private House house;
    private Boat boat;

    int IHouse.StreetNumber { get { return this.house.StreetNumber; } }
    double IBoat.SpeedKnots { get { return this.boat.SpeedKnots; } }
}

有偏见

从其中一个概念(更相似的那个)派生并为其他概念实现接口。

class HouseBoat : Boat, IHouse // is more like a Boat
{
    private House house; // model for the house aspects

    int IHouse.StreetNumber { get { return this.house.StreetNumber; } }
}

进一步阅读

这是一个很常见的问题,因为它自然如上文所述,Java 和 C# 都不允许多重继承。一个简单的google query with the right search terms 将提供丰富的材料。

【讨论】:

  • 很好的例子。我已经对这个问题进行了一些搜索(没有找到真正令人满意的解决方案),并且我相信我已经在 Effective Java 中阅读了这种模式。我理解组合优于继承的好处,但老实说,这种模式看起来很老套,随着接口和具体类数量的增长,会有大量的样板代码。但即使在我的具体情况下,也许也没有真正优雅的解决方案。我希望我可以在没有多重继承或聚合的情况下重组这个层次结构,但听起来你的解决方案仍然是最好的解决方法。谢谢。
猜你喜欢
  • 1970-01-01
  • 2012-01-30
  • 1970-01-01
  • 1970-01-01
  • 2017-06-07
  • 1970-01-01
  • 1970-01-01
  • 2012-03-01
  • 2018-11-26
相关资源
最近更新 更多