“构成超过继承”只是意味着“如果除了子类之外永远不会使用父类,它应该是组合”吗?

时间:2015-10-19 02:40:24

标签: oop inheritance design-patterns language-agnostic composition

我读了一些关于“遗产构成”,“在哪里使用构图/继承”,“是 - 关系......”或“Liskov替代原则”的帖子已有一段时间,但我不确定我是否得到关于“构成超过继承”的正确理念。

另外,根据我的经验,“继承的构成”似乎只是“如果除了子类之外永远不会使用父类,它应该是组合”,例如:

public class Parent{
}

public class Child1 extends Parent{
}

public class Child2 extends Parent{
}

如果除了Child1和Child2之外的代码中没有出现类“Parent”,那么Child1和Child2不应该是Parent的子类。

是吗?

3 个答案:

答案 0 :(得分:0)

继承是一种特定工具。组合是一种通用工具。两者都很有用,但在不同的背景下。

当您希望确保Foo类型的所有对象在每个方面都是Bar类型的对象时,继承很有用。这意味着不仅仅是实现相同的方法。这意味着Foo对象必须完美在每个外观可见的方面模拟Bar对象。如果他们不这样做,那么Liskov替换原则就会被违反,继承对于眼前的情况来说是一个糟糕的选择。

组成更为通用。它用于在多个类之间划分责任,同时仍允许它们之间进行适当的抽象和定义的交互。它不需要我刚才描述的特定的Liskov式关系。

"继承的构成"只是观察到组合是一种比继承更普遍的技术。因此,组合应该是我们在大多数情况下首先达到的工具,而不是继承。这并不意味着每次使用继承都是错误的,甚至这种继承本质上都是错误的。这是一种思考方式,而不是编码标准。

答案 1 :(得分:0)

我通常发现,当重用是目标时,继承可能看起来是一个有吸引力的解决方案。但是,在这种情况下,组合总是证明是更好的解决方案。

答案 2 :(得分:0)

组合 - 继承意味着不是使用父类和extend子类来构造类层次结构,而是应该执行以下操作:

class Foo {

    protected bar;
    protected baz;

    public function Foo(Bar _bar, Baz _baz) {
        bar = _bar;
        baz = _baz;
    }

}

换句话说,代替从基础父类继承一系列功能,您可以从独立对象获得相同的功能,而您最好将依赖注入到您的类中。

为什么呢?因为它提供了更大的灵活性在Foo extends Bar的情况下,Bar提供了一些基本功能,这对于一堆继承类很有用。现在,谁说这个功能对一堆其他不相关的类也没用? 所有你的类应该继承自Bar吗?是否应将所有常用功能填入Bar,因为所有类都是从它继承的?请不,这只会导致肥胖,单一,不可维护的基类。

相反,在他们自己的独立类中实现任何有用的常用方法的集合。仅对与密切相关的功能进行分组,将其分成不同的类是有意义的。然后将这些对象注入其他对象,以撰写一个新对象,该对象可以使用所有共享功能,而无需继承单个基类或定义抽象严格类层次结构。

如果他们共享同一个"业务逻辑"你应该只继承一个类。层次结构。例如,Cat extends Pet extends Animal完全符合逻辑。 Cat extends BaseConnectionManager少了。

如果您正在使用类层次结构进行类型提示,那么接口可以更好,更灵活地实现此目的。