Click here to Skip to main content
Click here to Skip to main content

Object Composition Over Inheritance

, 1 May 2011 CPOL
Rate this:
Please Sign up or sign in to vote.
Why to prefer object composition over inheritance

Introduction

From the early days of object oriented programming, there is a practice of using (rather abusing) inheritance. Many developers find comfort in defining an abstract class with common code implemented as virtual in base class. The major reason behind having this notion is to use override feature to modify behavior if required and to support code reusability. But doing so makes the code fragile over a period as base class starts to have more and more virtual methods which may not be required by all its derived classes.

In the below article, we will first see what it means by having composition in class designing. We will see how composition avoids the chronic 'object pollution issue', a byproduct of incorrect inheritance. This article explains the use of Composition in WPF applications, but it can very well be used in others as well.

Problem

Let's try to create a system having different types of users (Manager, Coder, and Leader). All users should have printer related operation access.System should support features as: Print, Fax, Scan, Email.

Mapping between Users and printer functionalities should be as follows:

  • Manager: Print, Fax, Scan, Email
  • Leader: Print, Scan
  • Coder: Print

Composition Solution

Let's try to solve this problem following composition. From the above problem definition, we can imagine some software entities and interface that could be used in implementation.

  • Interfaces: IPrinter, IEmployee
  • Classes: SuperPrinter, AvergePrinter, BasicPrinter, Manager, Coder, Leader

All the above mentioned inferences are plain representation of actors and actions defined in functional specifications. Nowhere in functional specification will you find a reference of printer as a plug-in for user operations. But if you carefully go through the spec, you can imagine interface IPrinterEnabled which would expose Printer interface as property allowing user to plug concrete printer object at construction time.

This kind of plug and play allows the system to stay flexible for future changes as user may reorder relationship between user and printer (e.g. allowing Leader to use SuperPrinter).

Please refer to the below class diagram explaining the same:

CompositeClassDiagram.png

You can also refer to the attached WPF example depicting implementation of it.

Inheritance Solution

I want to explain how we could have gone with the inheritance approach to solve the above problem. Note that the application will behave exactly the same for end users, oblivious to rigidity that system develops for change. I don't want to get into descriptions of implementation, you can check the class diagram and the attached code for understanding.

InheritanceClassDiagram.png

Referring to the above diagram and code, you will find that concrete user classes have been polluted by additional knowledge of printer features. Though they may internally use printer object to divert calls to appropriate execution, it makes compulsion on the developer to either come with a base class to have these printer signatures implemented and make them virtual so that can be overriden by derived classes or implement interface on all concrete classes.

Developers generally go for base class approach thinking that if IPrinterCommand interface changes over time, they would just be required to create the appropriate virtual method in base class. This is an insane mistake smelling the rottenness of design, as it requires modifying existing (& working) base class source code and updating all derived classes depend on the specific changes.

Conclusion

As you have seen, both the approaches have a few common classes, but there is a subtle variation in the way user classes use printer functionality. In the inheritance approach, printer functionality is inherited into derived user object showing tight coupling between users and print functionality. Whereas in Composition, user classes are made printer enabled by allowing them to be inherited from IPrinterEnabled interface, giving developer advantage of assigning printer functionality as plug-in to user objects. And we can very well say that user objects in composition approach are not polluted by printing functionality.

Note: I have used the above example as a random scenario. This may not be a practical scenario. Given the fact that all developers are used to hearing crazy requirements, this example won't drive you crazy.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

User-Rock
Software Developer
India India
No Biography provided

Comments and Discussions

 
QuestionCommand Pattern?? Pinmembernportelli21-Oct-13 6:41 
GeneralDon't Understand PinmemberMember-464203713-May-11 3:28 
GeneralRe: Don't Understand PinmemberRakeshGunijan13-May-11 3:42 
GeneralRe: Don't Understand PinmemberJoe_Developer13-May-11 3:47 
GeneralRe: Don't Understand PinmemberRakeshGunijan13-May-11 3:54 
GeneralHidden gem PinmemberSeth Morris10-May-11 8:48 
GeneralRe: Hidden gem PinmemberRakeshGunijan13-May-11 3:46 
GeneralMy vote of 3 PinmemberJustin Helsley9-May-11 12:45 
GeneralMy vote of 3 PinmemberToli Cuturicu2-May-11 9:36 
GeneralMy vote of 3 PinmemberCoolDadTx2-May-11 5:01 
GeneralOOD Concepts PinmemberCoolDadTx2-May-11 5:00 
Have you ever taken an OO design course? You seem to be saying that composition should be used instead of inheritance because it doesn't solve a specific problem you have. Inheritance is just one such tool in a design toolset. It should be used when it is appropriate. Composition, aggregation, adapters, etc are used when it doesn't.
 
The very core tenet of inheritance says that you only use it when you have is-a relationships. So if an is-a relationship exists then inheritance is appropriate because it simplifies design and maintenance. In your example printers are not users and vice versa. Therefore no properly trained developer would ever use inheritance. It doesn't fit the rules. In most cases adjective entities indicate the need for an interface/composition. In the case of printer command that is just a bad name. What exactly is a printer command? A command is a noun and it likely has attribute such as whether the command is valid and what it does. Thus inheritance is useful here. The example you gave though doesn't line up with this. A better name would have been Printable or SupportsPrinting. Both of these are adjectives which immediately send us toward interfaces/composition. Hence a user can get base functionality from the base class and also be printable via composition.
 
However there is a very clear is-a relationship between the various user entities. Therefore a proper design would implement the basic functionality a base class (using virtual for overriding). Creating an interface to represent a user is overkill since there is core functionality that will be shared and it is a maintenance problem to replicate this same implementation in each class. Worse is that interfaces in most languages are immutable and cannot share implementations therefore if you want to add new functionality later you have to go touch all the implementations you have. Maintenance just got chucked out the window.
 
In summary I don't particularly have a problem with your article other than the fact that you come off as saying that inheritance should be avoided in lieu of composition and that is just wrong. Both are required (along with other techniques). A good dev must understand when to use each one. If your writing a lot of code to implement a design then there is a good chance the design is wrong.
GeneralRe: OOD Concepts PinmemberRakeshGunijan2-May-11 5:25 
GeneralMy vote of 4 PinmemberBigJim612-May-11 1:55 
GeneralRe: My vote of 4 PinmemberRakeshGunijan2-May-11 5:03 
GeneralBoth samples are suboptimal PinmemberRobert Rohde2-May-11 0:13 
GeneralToo simplistic Pinmembergpgemini1-May-11 23:42 
GeneralRe: Too simplistic PinmemberRakeshGunijan2-May-11 4:48 
GeneralRe: Too simplistic Pinmembergpgemini2-May-11 4:55 
GeneralCan you fix the images please ? PinmemberRemi BOURGAREL1-May-11 23:32 
GeneralRe: Can you fix the images please ? PinmemberRakeshGunijan2-May-11 4:42 
GeneralRe: Can you fix the images please ? PinmemberRemi BOURGAREL2-May-11 5:20 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150327.1 | Last Updated 2 May 2011
Article Copyright 2011 by User-Rock
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid