【发布时间】:2016-10-02 10:51:06
【问题描述】:
我正在阅读这个wiki article 关于组合而不是继承的内容,在示例中他们使用了一个抽象类。假设您想完全避免他们使用抽象类,而只使用具体类。我想知道,我的例子是对构图的正确使用。假设我有以下 IGameobject 接口。
public interface IGameObject
{
string Name {get;}
}
以及以下武器界面:
//Note the IGameObject getter
public interface IWeapon
{
int Damage {get; }
IGameObject gameObject {get;}
}
通常,在我的游戏中,武器is-a IGameObject。但是,考虑到我们正在使用组合,根据 wiki 文章,它是 has-a 关系。
现在,我可以在创建 Sword 对象时这样做:
public class Sword : IWeapon
{
private IWeapon weaponObject;
public Sword(IWeapon weapon)
{
this.weaponObject = weapon;
}
public int Damage
{
get
{
return this.weaponObject.Damage;
}
}
public IGameObject gameObject
{
get
{
return this.weaponObject.gameObject;
}
}
}
我现在可以将我的剑存储在一个集合中,例如一个列表:
List<IWeapon> weapons = new List<IWeapon>();
weapons.add(swordObj)
并且仍然可以访问我的 IGameObject。
现在,我有 3 个问题:
- 我是否正确实现了合成?
- 我的 Sword 类是否也应该实现
IGameObject接口? - 我的 IWeapon 包含
IGameObject getter可以吗? (原因是,如果我将它存储为 IWeapon,没有 IGameObject getter,那么我将如何获得IGameObject的详细信息?)
【问题讨论】:
-
这看起来很奇怪 - 你的
Sword类只是IWeapon的包装。 -
您是否有理由避免在接口中添加行为添加方法而坚持使用属性?
-
这不是has-a。它是-a,因为同一个对象有多个方面。这不适合组合。组合并不比继承好。这是为了不同的东西。
-
这里的组合在
IWeapon和IGameObject之间而不是Sword和IWeapon之间。我希望Sword实现IWeapon并在该方案下包含IGameObject,并让Sword.Damage返回一些常量值。IWeapon和IGameObject之间的组合是否是一个好主意很难说。我可能希望IWeapon是IGameObject的子接口,并且根本不使用组合。 -
暂且不说组合与继承的问题,这里还有很多其他的问题。为什么“伤害”是武器的属性?肯定会通过考虑武器、持有者和目标的抵抗力来计算伤害;为什么这些东西中的任何一个都要对计算负责?这个领域有很多陷阱;如果您对这个主题感兴趣,请查看我的系列文章:ericlippert.com/2015/04/27/wizards-and-warriors-part-one
标签: c# oop inheritance composition