我正在努力模拟我遇到的问题,为简单起见,我已将其转换为Birds示例:
让我们说我们有鸟类,有些可以飞,有些可以,但是,它们都有翅膀,所有的飞鸟都以完全相同的方式飞行。
我的问题是什么更适合飞行能力?通常,使用接口来表示异能,但这需要我在每个Bird中实现Fly方法,尽管它们以相同的方式飞行。
另一个问题是,一只小鸟需要飞翔的翅膀,它可以代表一种“需要A"关系?它将是一个" Has-A"从鸟类的角度来看,但是从代表飞行能力的模块来看,它将是一个" Need-A"关系。
这是我目前的班级图。
为了解决上述一些问题,我将Bird转换为CanFlyBird继承的抽象类。 这是正确的方法吗?
因为我似乎还需要弄清楚默认情况下如何将Bird Wings of Bird类传递给Fly方法。
答案 0 :(得分:1)
你正走在正确的轨道上,但我认为你的第二个问题基本上是,"我怎样才能确保我不能构建一只无翅鸟?#34;。
" Need-A"关系仍然是一个" Has-A"关系。您有两种方法来实现该要求。
首先,您可以在Bird
:
Wing wings = new Wing(); //as a field or
public Wing Wings { get; set; } = new Wing() //as a property
或者第二,在这种情况下可能更正确,在构造函数中需要Wing:
public Bird(Wing wing) { this.wings = wing; }
至于#34; Fly()"我同意其他人并推荐一种虚拟方法。您可以稍后在子类中覆盖它,如果您决定有一天将游泳计为飞行,则允许您对Penguin子类进行最小的更改以实现您的更改。
答案 1 :(得分:1)
我有建议,你可以取出继承链的CanFlyBird
输出,而不是通过构造函数传递它,意味着使用组合,
所以它会变成
Bird继承了Eagle和Penguin,并将CanFlyBird作为构造函数参数传递给Eagle。
代码
interface IFly {
void fly();
}
和CanFlyBird将是
public class CanFlyBird : IFly {
public void Fly() {}
}
和鹰将
public class Eagle : Bird {
private readonly IFly _fly;
public Eagle (IFly fly) {
_fly = fly;
}
}
我的建议是利用Composition而不是继承贷款链。
通过这种方式,如果我想制作canFlyBird
类的变体,我可以在不改变现有类的情况下创建它
所以它会变成Bird has a flying capability
或者如果您想遵循当前结构,那么
你可以将fly方法作为CanFlyBird类中的虚方法,所以如果有人想覆盖它,那么该类可以覆盖其他使用基本版