组合或继承


Composition or inheritance

interface DoSomething
{
    public function do();
    public function getId();
}
class DoSomethingGood implements DoSomething 
{
    private $dependency;
    private $id;
    public function __construct($id, $dependency)
    {
        $this->dependency = $dependency;
        $this->id = $id;
    }
    public function do()
    {
        if ($this->dependency->isActive()) {
            return true;
        }
        return false;
    }
    public function getId()
    {
        return $this->id;
    }
}
class DoSomethingBad implements DoSomething 
{
    private $id;
    public function __construct($id)
    {
        $this->id = $id;
    }
    public function do()
    {
        return false;
    }
    public function getId() {
        return $this->id;
    }
}

我应该在这里使用组合还是继承会更好? 区别在于这些类如何实现 do() 方法。 第一个类具有它所需的依赖关系和一些内部逻辑来决定,而另一个类则更简单。

继承是一种语义关系。不是构图。一个常见的错误是通过使用继承而不是组合来分解代码。

只见利斯科夫替换原理

我认为你应该从概念上考虑这段代码。这些类之间的关系是什么?是关系还是关系?

如果可以说DoSomethingGoodDoSomething,那么继承很好地反映了这一点。您可以让继承器替换继承的类和适当的多态性。应用程序的其余部分将很好地通过此选择进行,因为它反映了您对此的看法。

如果你可以说DoSomethingDoSomethingGood那么你应该使用构图。特别是如果你可以有很多DoSomethingGood.同样,如果这在概念上是正确的,则其余代码很容易编写。

有时看起来你可以对两者都说"是",并且线条模糊,但你应该真正在概念级别考虑它,而不是在代码级别。特别是如果你想理解模式,而不仅仅是"代码重用",这是一种关于继承的推理方式。

当你的选择错误时,编码将变得繁琐、违反直觉、不必要的复杂或完全不可能(矛盾)。如果发生这种情况,请回到绘图板并重新考虑您的选择。

也就是说,你几乎是唯一一个可以说出你的想法和你想做什么的人。如果您使用像DoSomethingGood这样的名称,那就模棱两可了。

当你说CatDogAnimal时,要容易得多。在这里很容易说出使用什么(断言"Cat是一个Animal"在直觉上是正确的)。