为什么推荐使用组合而尽量不用继承?

时间:2022-09-16 10:43:56
很多面向对象的书里面推荐程序员使用组合而尽量不要用继承。请问为什么。

  如何实现组合呢?

  请多指教。

11 个解决方案

#1


如果是单根继承也一样。

#2


但如果要实现构造设计模式
不使用继承能行么?

组合灵活性更大,而且易于理解和使用

#3


如果你对这两者仔细体会的话:

    其实“组合”在一定程度上相当于“私有继承”,相同点就不用说了,这里,我门应该区分他们的异同。
    对于A、B两个对象,他们之间有一种从属关系的话:
(为什么我们愿意用组合)
    一、组合可以保证保证在主方可以得到多个从方的事例,然而如果是私有继承的话,他只能保证主方拥有从方的一个事例(注意,这里抛开了“基类”和“衍生类”的说法,其实主方就是衍生类,从方就是基类);
    二、私有继承形式可能引入不必要的多重继承;
(为什么我们愿意用私有继承)
    三、私有继承形式允许主方的成员可以实现指针的自动upcast;
    四、私有继承形式允许访问从方的保护成员(这是唯一能有尽可能不破坏封装的办法了);
    五、私有继承形式允许重写虚函数,要知道虚函数是C++的六大令人兴奋的特性之一;
    六、私有继承形式提供了简单直接的对从方的控制(调用)。

#4


注意:上面的第四点可能有说得有点模糊!
不理解的话再说

#5


因为继承用得太多人。新手们一见到有点关系的就想到继承,但继承不能解决一切问题。

#6


就象人们在说到继承时,往往只看到公有继承,而忽略了其他的继承方式,其实,在oo方面,有很多成功的范例,包括组合及一般化。

#7


is a那么就是继承
has a那么就是组合

没有百分百的规定,看怎么实现符合实际情况了

#8


详见 pattern design:
Inheritance versus Composition
The two most common techniques for reusing functionality in object-oriented systems are class inheritance and object composition. As we've explained, class inheritance lets you define the implementation of one class in terms of another's. Reuse by subclassing is often referred to as white-box reuse. The term "white-box" refers to visibility: With inheritance, the internals of parent classes are often visible to subclasses.

Object composition is an alternative to class inheritance. Here, new functionality is obtained by assembling or composing objects to get more complex functionality. Object composition requires that the objects being composed have well-defined interfaces. This style of reuse is called black-box reuse, because no internal details of objects are visible. Objects appear only as "black boxes."

Inheritance and composition each have their advantages and disadvantages. Class inheritance is defined statically at compile-time and is straightforward to use, since it's supported directly by the programming language. Class inheritance also makes it easier to modify the implementation being reused. When a subclass overrides some but not all operations, it can affect the operations it inherits as well, assuming they call the overridden operations.

But class inheritance has some disadvantages, too. First, you can't change the implementations inherited from parent classes at run-time, because inheritance is defined at compile-time. Second, and generally worse, parent classes often define at least part of their subclasses' physical representation. Because inheritance exposes a subclass to details of its parent's implementation, it's often said that "inheritance breaks encapsulation" [Sny86]. The implementation of a subclass becomes so bound up with the implementation of its parent class that any change in the parent's implementation will force the subclass to change.

Implementation dependencies can cause problems when you're trying to reuse a subclass. Should any aspect of the inherited implementation not be appropriate for new problem domains, the parent class must be rewritten or replaced by something more appropriate. This dependency limits flexibility and ultimately reusability. One cure for this is to inherit only from abstract classes, since they usually provide little or no implementation.

Object composition is defined dynamically at run-time through objects acquiring references to other objects. Composition requires objects to respect each others' interfaces, which in turn requires carefully designed interfaces that don't stop you from using one object with many others. But there is a payoff. Because objects are accessed solely through their interfaces, we don't break encapsulation. Any object can be replaced at run-time by another as long as it has the same type. Moreover, because an object's implementation will be written in terms of object interfaces, there are substantially fewer implementation dependencies.

Object composition has another effect on system design. Favoring object composition over class inheritance helps you keep each class encapsulated and focused on one task. Your classes and class hierarchies will remain small and will be less likely to grow into unmanageable monsters. On the other hand, a design based on object composition will have more objects (if fewer classes), and the system's behavior will depend on their interrelationships instead of being defined in one class.

That leads us to our second principle of object-oriented design:

Favor object composition over class inheritance. 
Ideally, you shouldn't have to create new components to achieve reuse. You should be able to get all the functionality you need just by assembling existing components through object composition. But this is rarely the case, because the set of available components is never quite rich enough in practice. Reuse by inheritance makes it easier to make new components that can be composed with old ones. Inheritance and object composition thus work together.

Nevertheless, our experience is that designers overuse inheritance as a reuse technique, and designs are often made more reusable (and simpler) by depending more on object composition. You'll see object composition applied again and again in the design patterns.

#9


我也是很疑惑,关注。

#10


不懂你就不要这样做嘛。等你用继承用得很爽了,自然就知道为什么了。没有遇到这些问题,谁能给你解释清楚?

#11


使用组合,可以获得更多的灵活性,你甚至可以在运行的时候才决定把哪几个类组合在一起。
使用继承,他是一种高度的耦合,派生类和基类被紧紧的绑在一起,灵活性大大降低,而且,滥用继承,也会使继承树变得又大又复杂,很难理解和维护

#1


如果是单根继承也一样。

#2


但如果要实现构造设计模式
不使用继承能行么?

组合灵活性更大,而且易于理解和使用

#3


如果你对这两者仔细体会的话:

    其实“组合”在一定程度上相当于“私有继承”,相同点就不用说了,这里,我门应该区分他们的异同。
    对于A、B两个对象,他们之间有一种从属关系的话:
(为什么我们愿意用组合)
    一、组合可以保证保证在主方可以得到多个从方的事例,然而如果是私有继承的话,他只能保证主方拥有从方的一个事例(注意,这里抛开了“基类”和“衍生类”的说法,其实主方就是衍生类,从方就是基类);
    二、私有继承形式可能引入不必要的多重继承;
(为什么我们愿意用私有继承)
    三、私有继承形式允许主方的成员可以实现指针的自动upcast;
    四、私有继承形式允许访问从方的保护成员(这是唯一能有尽可能不破坏封装的办法了);
    五、私有继承形式允许重写虚函数,要知道虚函数是C++的六大令人兴奋的特性之一;
    六、私有继承形式提供了简单直接的对从方的控制(调用)。

#4


注意:上面的第四点可能有说得有点模糊!
不理解的话再说

#5


因为继承用得太多人。新手们一见到有点关系的就想到继承,但继承不能解决一切问题。

#6


就象人们在说到继承时,往往只看到公有继承,而忽略了其他的继承方式,其实,在oo方面,有很多成功的范例,包括组合及一般化。

#7


is a那么就是继承
has a那么就是组合

没有百分百的规定,看怎么实现符合实际情况了

#8


详见 pattern design:
Inheritance versus Composition
The two most common techniques for reusing functionality in object-oriented systems are class inheritance and object composition. As we've explained, class inheritance lets you define the implementation of one class in terms of another's. Reuse by subclassing is often referred to as white-box reuse. The term "white-box" refers to visibility: With inheritance, the internals of parent classes are often visible to subclasses.

Object composition is an alternative to class inheritance. Here, new functionality is obtained by assembling or composing objects to get more complex functionality. Object composition requires that the objects being composed have well-defined interfaces. This style of reuse is called black-box reuse, because no internal details of objects are visible. Objects appear only as "black boxes."

Inheritance and composition each have their advantages and disadvantages. Class inheritance is defined statically at compile-time and is straightforward to use, since it's supported directly by the programming language. Class inheritance also makes it easier to modify the implementation being reused. When a subclass overrides some but not all operations, it can affect the operations it inherits as well, assuming they call the overridden operations.

But class inheritance has some disadvantages, too. First, you can't change the implementations inherited from parent classes at run-time, because inheritance is defined at compile-time. Second, and generally worse, parent classes often define at least part of their subclasses' physical representation. Because inheritance exposes a subclass to details of its parent's implementation, it's often said that "inheritance breaks encapsulation" [Sny86]. The implementation of a subclass becomes so bound up with the implementation of its parent class that any change in the parent's implementation will force the subclass to change.

Implementation dependencies can cause problems when you're trying to reuse a subclass. Should any aspect of the inherited implementation not be appropriate for new problem domains, the parent class must be rewritten or replaced by something more appropriate. This dependency limits flexibility and ultimately reusability. One cure for this is to inherit only from abstract classes, since they usually provide little or no implementation.

Object composition is defined dynamically at run-time through objects acquiring references to other objects. Composition requires objects to respect each others' interfaces, which in turn requires carefully designed interfaces that don't stop you from using one object with many others. But there is a payoff. Because objects are accessed solely through their interfaces, we don't break encapsulation. Any object can be replaced at run-time by another as long as it has the same type. Moreover, because an object's implementation will be written in terms of object interfaces, there are substantially fewer implementation dependencies.

Object composition has another effect on system design. Favoring object composition over class inheritance helps you keep each class encapsulated and focused on one task. Your classes and class hierarchies will remain small and will be less likely to grow into unmanageable monsters. On the other hand, a design based on object composition will have more objects (if fewer classes), and the system's behavior will depend on their interrelationships instead of being defined in one class.

That leads us to our second principle of object-oriented design:

Favor object composition over class inheritance. 
Ideally, you shouldn't have to create new components to achieve reuse. You should be able to get all the functionality you need just by assembling existing components through object composition. But this is rarely the case, because the set of available components is never quite rich enough in practice. Reuse by inheritance makes it easier to make new components that can be composed with old ones. Inheritance and object composition thus work together.

Nevertheless, our experience is that designers overuse inheritance as a reuse technique, and designs are often made more reusable (and simpler) by depending more on object composition. You'll see object composition applied again and again in the design patterns.

#9


我也是很疑惑,关注。

#10


不懂你就不要这样做嘛。等你用继承用得很爽了,自然就知道为什么了。没有遇到这些问题,谁能给你解释清楚?

#11


使用组合,可以获得更多的灵活性,你甚至可以在运行的时候才决定把哪几个类组合在一起。
使用继承,他是一种高度的耦合,派生类和基类被紧紧的绑在一起,灵活性大大降低,而且,滥用继承,也会使继承树变得又大又复杂,很难理解和维护