"有一个"vs"是一个" - 代码味道决定

Ben*_*jol 2 oop inheritance composition

我昨天在一个继承自Bar的Foo类中写了这个:

public override void AddItem(double a, int b)
{
    //Code smell?
    throw new NotImplementedException("This method not usable for Foo items");
}
Run Code Online (Sandbox Code Playgroud)

随后想知道这是否可能表明我应该使用 Bar,而不是继承它.

还有哪些"代码味道"可以帮助在继承和组合之间做出选择?

编辑我要补充一点,这是一个片段,还有其它方法相同之处,我只是不想去考虑太多的细节.我必须分析切换到合成的含义,并想知道是否可能有其他"代码味道"可能有助于提高平衡.

Leo*_*Hat 18

您上面给出的示例显然是代码味道.该AddItem方法是基类的行为Bar.如果Foo不支持该AddItem行为,则不应继承Bar.

让我们想一个更现实的(C++)示例.假设你有以下课程:

class Animal
{
    void Breathe() const=0;
}

class Dog : public Animal
{
    // Code smell
    void Breathe() { throw new NotSupportedException(); }
}
Run Code Online (Sandbox Code Playgroud)

基本抽象类Animal提供了一种纯粹的虚拟Breathe()方法,因为动物必须呼吸才能生存.如果它没有呼吸,那么根据定义它不是动物.

通过创建一个Dog继承Animal支持该Breathe()行为的新类,您违反了Animal该类规定的合同.可怜的狗将无法生存!

公共继承的简单规则是,只有在派生类对象真正"是"基类对象时才应该这样做.

在您的特定示例中:

  • Foo不支持合同AddItem()规定的行为Bar.
  • 因此,根据定义,Foo"不是" Bar,不应该继承它.