Object composition and inheritance are two techniques for reusing functionality in object-oriented systems . Class inheritance, or subclassing, allows a subclass' implementation to be defined in terms of the parent class' implementation. This type of reuse is often called white-box reuse. This term refers to the fact that with inheritance, the parent class implementation is often visible to the subclasses.
Object composition is a different method of reusing functionality. Objects are composed to achieve more complex functionality. This approach requires that the objects have well-defined interfaces since the internals of the objects are unknown. Because objects are treated only as "black boxes," this type of reuse is often called black-box reuse.
Each of these two methods have advantages and disadvantages. The advantage of class inheritance is that it is done statically at compile-time and is easy to use. The disadvantage of class inheritance is that the subclass becomes dependent on the parent class implementation. This makes it harder to reuse the subclass, especially if part of the inherited implementation is no longer desirable. According to , "inheritance breaks encapsulation." One way around this problem is to only inherit from abstract classes. Another problem with class inheritance is that the implementation inherited from a parent class cannot be changed at run-time.
In object composition, functionality is acquired dynamically at run-time by objects collecting references to other objects. The advantage of this approach is that implementations can be replaced at run-time. This is possible because objects are accessed only through their interfaces, so one object can be replaced with another just as long as they have the same type. In addition, since each object is defined in terms of object interfaces, there are less implementation dependencies . The disadvantage of object composition is that the behavior of the system may be harder to understand just by looking at the source code. A system using object composition may be very dynamic in nature so it may require running the system to get a deeper understanding of how the different objects cooperate.
In general, object composition should be favored over inheritance. It promotes smaller, more focused classes and smaller inheritance hierarchies. Most designers overuse inheritance, resulting in large inheritance hierarchies that can become hard to deal with. A design based on object composition will have less classes, but more objects. The behavior of such a system depends more on the interrelationships between objects rather then being defined in a particular class .
However, inheritance is still necessary. You cannot always get all the necessary functionality by assembling existing components. This is because "the set of components is never quite rich enough in practice" . Inheritance can be used to create new components that can be composed with old components. As a result, the two methods work together.
Due to the flexibility and power of object composition, most design patterns emphasize object composition over inheritance whenever it is possible. Many times, a design pattern shows a clever way of solving a common problem through the use of object composition rather then a standard, less flexible, inheritance based solution.