【问题标题】:Problem with inherited classes in C#C#中继承类的问题
【发布时间】:2010-04-23 22:14:43
【问题描述】:

我有一个名为“Entity”的类,它有两个子类:“Creature”和“Item”。 (我正在制作游戏。) Creature 有两个功能,称为“攻击”,一种用于攻击生物,另一种用于攻击物品。到目前为止,一切正常。

现在我正在处理拍摄位,所以我有一个名为 SelectTarget() 的函数。它获取玩家视野中玩家可以射击的所有实体(生物和物品)并让玩​​家选择一个。

所以问题就在这里:SelectTarget() 返回一个实体,但我需要一些代码来确定该实体是生物还是物品,并适当地处理它。

由于没有任何代码,这个问题看起来有点空洞,而且我不能 100% 确定我的解释是否足够好,这就是我所在的位置:

if (Input.Check(Key.Fire)) {
    Entity target = Game.State.SelectTarget.Run();
    this.Draw();
    if (target != null) {     
        //Player.Attack(target);
        // This won't work, because I have:
        //   Player.Attack((Creature)Target)
        //   Player.Attack((Item)Target)
        // but nothing for Entity, the parent class to Creature and Item.
        return true;
    }
}

(如果游戏的布局看起来很奇怪,那就是 Roguelike。)

【问题讨论】:

  • 仅供参考,您正在寻找的通常称为“双重虚拟调度”,其有用的典型示例是“两个事物在游戏中发生碰撞,需要调用正确的方法根据它们的运行时类型对它们进行排序”。 C# 是一种单一的虚拟调度语言;正如 SLaks 所指出的,在单一调度语言中实现双重调度的标准模式是访问者模式。

标签: c# class inheritance


【解决方案1】:

您正在寻找Visitor pattern

【讨论】:

  • 所以一个实体会有一个方法GetAttackedBy(Player) 来调用Player.Attack 的正确重载?很奇怪,但是 +1。
【解决方案2】:

如果引入CreatureItem 都实现的接口IAttackable 怎么样。 Player.Attack 将具有新签名 Player.Attack(IAttackable target)。每个实现IAttackable 的对象都可以获得减去生命值的方法,或者检索防御值(用于计算要减少的生命值)等等......

【讨论】:

  • 啊,也可以这样做...我是 C# 的新手,并且仍在研究接口。实际上,这个例子让事情更清楚了,谢谢!
【解决方案3】:

尝试类似:

if(target is Creature)
      player.Attack(target as Creature);
else if(target is Item)
      player.Attack(target as Item);

【讨论】:

  • 是的,可以改为检查空值
  • 谢谢!我不知道“is”和“as”甚至存在。整洁的功能,感谢您的快速回复!
  • 这听起来像是接口的问题 - 在实现 if/else 链或切换之前总是三思而后行 - 几乎总是有更好的 OOP 方法
  • 这当然可行,但我认为这不是一个非常理想的设计。这是接口派上用场的情况之一,而不是做不必要的事情,例如检查和强制转换以及处理特殊情况。你看我的回答了吗?
  • 根据你打算拥有多少不同类型的实体,这个代码块最终可能会很大......我会按照@Philip的建议选择IAttackable接口
猜你喜欢
  • 2012-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-11
相关资源
最近更新 更多