Context

Two of the main techniques for re-using code are Class Inheritance and Object Composition.Class Inheritance defines a new class in terms of an existing class. A subclass inherits both data and protocol from its superclass.Object Composition defines a new class as containing an instance of one or more existing classes. This type of class inherits nothing from the objects it contains. This pattern should help you decide which technique to use.

Solution

Class Inheritance should be used only if instances of the new class can be used in all situations where the existing class can be used. Class Inheritance not inappropriate if the subclass needs to stub out behaviour implemented by the superclass. Use Object Composition if instances of the new class do not require the protocol of the superclass.

Example

Consider a new class Stack which is implemented as an Array.We can either subclassStackfromArray(classinheritance):

Array variableSubclass: #Stack
        instanceVariableNames: ''
        classVariableNames: ''
        poolDictionaries: ''

or we can use an instance of Array as a data member of Stack(object composition):

Object subclass: #Stack
        instanceVariableNames: 'array'
        classVariableNames: ''
        poolDictionaries: ''

In this case, it would make more sense to use objectcomposition (the second example). Instances ofStackdonot need to inherit the extensiveCollectionprotocol.

Known Uses

The PropertyManager class uses Object Composition. Itcontains an instance ofWeakIdentityDictionaryratherthan subclassing fromWeakIdentityDictionary. As aresult, the protocol ofPropertyManageris very compact.

组合与继承的对应关系(如果在类A中包含类C类型的属性,那么就把类A称为整体类或者包装类,把类C称为局部类或者被包装类。

组 合 关 系

继 承 关 系

局部类

父类

整体类

子类

从整体类到局部类的分解过程

从子类到父类的抽象过程

 

从局部类到整体类的组合过程

从父类到子类的扩展过程

 

组合关系的分解过程对应继承关系的抽象过程


比较组合关系与继承关系

组 合 关 系

继 承 关 系

优点:不破坏封装,整体类与局部类之间松耦合,彼此相对独立

缺点:破坏封装,子类与父类之间紧密耦合,子类依赖于父类的实现,子类缺乏独立性

优点:具有较好的可扩展性

缺点:支持扩展,但是往往以增加系统结构的复杂度为代价

优点:支持动态组合。在运行时,整体对象可以选择不同类型的局部对象

缺点:不支持动态继承。在运行时,子类无法选择不同的父类

优点:整体类可以对局部类进行包装,封装局部类的接口,提供新的接口

缺点:子类不能改变父类的接口

缺点:整体类不能自动获得和局部类同样的接口

优点:子类能自动继承父类的接口

缺点:创建整体类的对象时,需要创建所有局部类的对象

优点:创建子类的对象时,无须创建父类的对象

继承关系最大的弱点是打破了封装,子类能够访问父类的实现细节,子类与父类之间紧密耦合,子类缺乏独立性,从而影响了子类的可维护性。为了尽可能地克服继承的这一缺陷,应该遵循以下原则:

·精心设计专门用于被继承的类,继承树的抽象层应该比较稳定。

·对于父类中不允许覆盖的方法,采用final修饰符来禁止其被子类覆盖。

·对于不是专门用于被继承的类,禁止其被继承。

·优先考虑用组合关系来提高代码的可重用性。