我读了一些关于“遗产构成”,“在哪里使用构图/继承”,“是 - 关系......”或“Liskov替代原则”的帖子已有一段时间,但我不确定我是否得到关于“构成超过继承”的正确理念。
另外,根据我的经验,“继承的构成”似乎只是“如果除了子类之外永远不会使用父类,它应该是组合”,例如:
public class Parent{
}
public class Child1 extends Parent{
}
public class Child2 extends Parent{
}
如果除了Child1和Child2之外的代码中没有出现类“Parent”,那么Child1和Child2不应该是Parent的子类。
是吗?
答案 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
少了。
如果您正在使用类层次结构进行类型提示,那么接口可以更好,更灵活地实现此目的。