Composition Instead Of Inheritance

I wish there were a good example of this.

I hope you'll settle for "off-the-cuff" instead of "good". I suspect you've read something like the GangOfFour book where they tell you to use CompositionInsteadOfInheritance. This is the classic "Is-A" vs "Has-a" question. I'll explain more after the example:

Starting with:

 class Mouth {
 public:
 void eat(Food bite);
 };
Now, if we were to define a "Person" class that needs to be able to "eat()" using inheritance, we'd have:

 class Person: public Mouth {
 };
If we were to do the same using composition, we might have:

 class Person {
 public:
 void eat(Food bite) {
 itsMouth.eat(bite);
 }
 private:
 Mouth itsMouth;
 };
(Note: There is a version that uses composition but violates the LawOfDemeter that I didn't bother with. Basically, it involves making a method like "Person::getMouth()", but doing that sort of thing is regrettable - don't do that).

You can see that the first involves less keystrokes than the second. Its advantages pretty much end there.

Ask the "Is-a vs Has-a" question: Which is better, "A person is a mouth", or "A person has a mouth"? Obviously, the second. If you ignore the more correct answer to this question, you end up with code that doesn't communicate its intent very clearly.

 class Food {};
 class DirtyFood? : public Food {};
 class SwallowableFood? : public Food {};
 class TornGroundShreddedFood? : public SwallowableFood? {};

template<typename I, typename O> class Eater : public Functor<I,void> { virtual Functor<O> destination(); virtual void operator()(I i) { destination()(process(i)); } virtual O process(I) = 0; }; class Mouth : public Eater<Food,DirtyFood?> { Person thePerson; // (linkage type '(a)' - could have 'Teeth' directly, or just a generic functor object that can wrap whatever). Teeth destination() { return thePerson's teeth; } DirtyFood? process(Food f) { thePerson.taste(f); return add_germs_and_saliva(f); } }; class Teeth : public Eater<Food,TornGroundShreddedFood?> { Person thePerson; bool bToothAche; Esophagus destination() { return thePerson's esophagus; } TornGroundShreddedFood? process(Food f) { if(bToothAche) throw "has a toothache!"; if(chewable(f)) return tear(grind(shred(f))); else { bToothAche = true; throw "Yeouch! can't eat this!" } } }; class Esophagus : public Eater<SwallowableFood?,SwallowableFood?> { Person thePerson; Stomach destination() { return thePerson's stomach; } SwallowableFood? process(SwallowableFood? f) { thePerson.stopBreathing(); // fails if person is laughing too hard thePerson.gulp(swallowable_traits(f)); // might throw 'choked!' thePerson.startBreathing(); // fails if person is choking return f; } }; class Stomach : public Eater<SwallowableFood?, NutritiousGruel?> { Person thePerson; SmallIntestine? destination() { return thePerson's intestines.begin(); } ... etc. ... };

// note: the above works much better in an implicitly concurrent message-passing or object-passing system, especially when the chains get really long.

"A valuable side-effect of modelling object relations using composition is that it exposes dubious design far more easily than inheriting implementation would. In the simple example above, it is clear the Person object doesn't add anything useful to the process of eat(). This immediately suggests several changes: eat() could involve a state change for Person; Mouth could perhaps chew() rather than eat(); Person could pass the result of Mouth.chew() (if any) to some other object. Each of these would add to the clarity of the design. In short: composition does not encourage, but rather exposes, violations of the LawOfDemeter. -- RichardCordova"

[For more examples of disadvantages, you'll have to wait. Either some other fine Wikizen or myself at a later time will pick up where I'm leaving off for now.]

Yes, a good example. Sometimes, however, "Is-a" and "Has-a" are not so distinct. For example the relationship between a window and a rectangle. "A Window is a Rectangle" and "A Window has a rectangle" both sound reasonable.

Until you think about non-rectangular windows. A Window Has-A Shape. A Rectangle Is-A Shape. Thinking a little more about the problem domain (even if the current application has no need of non-rectangular windows) can shed some light on the relationship between the objects in it - more than simply thinking about their behaviour could.

Also, most windows have several rectangles - there may be a "client area" with the real content, and a "non-client area" with meta-data like a border, titlebar, resizing handles etc. When you realize this it becomes harder to use "is-a" for just one of them.

Another example of where "Is-a" and "Has-a" are not often clear is collections. It is often a matter of interpretation whether something is a collection or has a collection. I've often had to switch from one to the other midway through development.

Forget about about the "Is-a" and "Has-a" and look at the code. If, as shown in your example, you want to expose the interface of a lower level class from an higher level class, use inheritance. If you merely want to use functionality from the lower level class within the higher level class, use composition.

What are good practices for constructing delegate classes in a Composition class? See ConstructingDelegates


CompositionInsteadOfInheritance is somewhat related to DelegationIsInheritance. It also tends to reflect implicit cultural assumptions. For some reason (perhaps simple history), the American OO community has always tended to think in terms of Inheritance and Specialization. This may reflect the influence of early and naive Smalltalk activity. The European OO community, conversely, has always tended to think in terms of Delegation and Composition.

MartinFowler has written some pretty good material exploring some of these tradeoffs. An example that may be more immediate than Person and Mouth is Person, Employee, and Customer. How shall we model the relationships among these ideas? More than one naive developer has written code along the lines of:

 public class Person {}
 public class Employee extends Person {}
 public class Customer extends Person {}
and so forth. For certain classes of problems, this works just fine. On the other hand, sometimes a Customer is also an Employee, and this is where life gets interesting. Plus, a customer may grow their own business and become an organization instead a Person. I am not convinced one can know ahead of time which hierarchies are safe and which will "degenerate" in the future.

If the class starts to degenerate, fix it. That is what refactoring is all about. Make an initial choice and start using it. If the choice was wrong, it really is not a lot of effort to change it to something better.

Well, sure. Nevertheless, such refactoring is significantly easier (especially in Java and CeePlusPlus) when the initial design reflects a bias towards CompositionInsteadOfInheritance.

What becomes simpler? I've done a lot of C++ programming and I haven't seen advantages one way or the other. In some cases composition is more appropriate, other cases inheritance is more appropriate. Could you provide more information on why refactoring would be simpler?

Inheritance, pretty much by construction, leverages the properties of the ancestors for use by the descendents. As in any lever, this means that changes to those ancestors are "heavier". For example, variable names and definitions tend to be repeated in code (a member named "foobar" tends to spawn methods like "initializeFoobar", finalizeFoobar", and so on). Thus, when classes that are closer to the root of the inheritance tree need to be refactored, there is more work to do. Composition tends to distribute this leveraged code over several more independent classes (sometimes with an associated increase in code volume). Internal changes to participants in the "Decorator", "Strategy" and "Visitor" patterns tend to be limited to the class being changed. In my experience, two prices are often paid: (1) increased code volume and (2) longer "code chains" (a calls b calls c ... calls z). Nevertheless, my experience has been that refactoring is easer and lighter in composition-based designs, in comparison to inheritance-based designs.

Thus, if instead of:

 public class Person {}
 public class Employee extends Person {}
 public class Customer extends Person {}
we have
 public class Person {}

public class Employee { private Person person; }

public class Customer { private Person person; }
I can now refactor Person (specifically, the internals of how Person accomplishes its behavior) without affecting Employee or Customer at all.

I don't follow your argument. If one changes the names of methods within person, the delegators from Customer and Employee still need to be changed as well. If the name refactoring is needed, then the Person interface to Customer and Employee would need the same refactoring. The argument appears to be one against inappropriate use of inheritance rather than saying that composition should be used in place of inheritance.

Changes to interface methods have to propagate in either approach. The difference is in the rest of the code. I hesitate to use words like "private", "protected" and "public" because they don't really mean the same. Many classes require public methods that are not part of the interface for the class. In the implementation of an interface method inside Customer, I might call a method from Person that is "public" but NOT specified in the external module interface. Members and statics demonstrate similar differences. Suppose I refactor Person into multiple classes - if Employee and Customer delegate to it, and my refactoring preserves the external interface of Person, then I need not touch Employee or Customer.

If you are not exposing the interface to Person from Employee and Customer, then do not use inheritance. If, however, the code needs to manipulate Employee objects and Customer objects as Person objects, the you need to use inheritance. It is not that one is better than the other, it is merely a matter of using the correct approach for the task at hand.

You still don't need to use inheritance. Just make an IPerson interface and have a method accept IPerson, then manipulate the objects off methods in the interface. There is NEVER a case where you need inheritance, all can be done using composition.

Here's a concrete way to appreciate the difference: if Employee and Customer inherit from Person, they need to be recompiled after every change to Person. If Employee and Customer delegate to Person, they only need to be recompiled when the externals of Person change. If you remember the dark ages of the CeeLanguage, do you recall building an "exports.h" file for each module (often wrapped in a "<moduleName>.h" file), included by consumers of that module, that declared the procedures and datatypes exported by the module? The purpose was to provide a convenient hook to a makefile so that consumers would be rebuilt only when the exports.h changed.

This is related to the ContactAndAddressModels debate.

In C++, most dependency checkers will force a recompile based on any change in the *.h file, either due to public or private members. This is true for either inherited interfaces or for internal classes. Changes to the *.cpp (or whatever extension) will not require a recompile beyond the affected file. In pure C, my preferred approach was to declare "private" methods as static methods within the *.c file and only include extern methods within the *.h file. Unfortunately, when you do this in C++, you lose the "this" pointer.


Philosophic arguments whether inheritance or delegation is superiour lead nowhere. Considering a real application leads to a good design. In the case of Employees and Customers ask yourself: Is there any method on every Person, the behaviour of which differs between Customers and Employees? If so, use inheritance, but I cannot see any.

Then ask what you're really trying to accomplish. I think, in this case there are only Persons and they might have one or more Business Relationships with you, or even more practical, they might be your Customers and/or Employees.

You end up with Persons and two containers of Customers and Employees. Far simpler, less philosophical, and above all just works.

A better question is why you're trying to create a simulator for Persons, Customers, and Employees. Most business applications are intended to reflect reality, not impose upon it. In ObjectOriented code, you 'create' employees and customers - or, more accurately, simulacra thereof - and make them behave as you desire. Though I'm sure that a few exceptions exist, most businesses are interested in finding and keeping real customers, not creating and simulating virtual ones. See ObjectVsModel.


To me, encapsulation is the most important quality of OOP programming. If done correctly, it keeps code and data that have an intimate relationship, in close proximity so that changes don't affect code in unknown locations. Inheritance is only useful if you use the Classes, at the different levels, in multiple cases. If a "person" Class is defined and then a "customer" Class extends that Class, you would just merge them into one if the "person" Class wasn't used by some other Class. By definition, a parent class will be used by at least 2 different children Classes. This means that changes to that parent change more than one child Class and encapsulation is broken. Composition on the other hand, makes a Class stand alone and doesn't break the encapsulation. If "person" is an object inside of either "customer" or "employee" and you want to change that object's functionality, you don't break either child object unless you change the existing interface. The "person" part of the child objects then becomes a "stand alone", encapsulated object that can be tested separately from any other Class definition. For simple examples, it is not obvious that one is better than the other but as the pyramid or height of the Class hierarchy gets bigger, the encapsulating quality of Composition is clearly better than Inheritance. -- DavidClarkd


I feel this discussion is on a totally wrong level. It's like you want to compare the safety or luxury of two buildings and speak about helmets that workers had used during construction.

First of all, both (inheritance and composition) are mechanisms that can be used for a specific purpose. Therefor any statement like "<A> is better than <B>" is syntactically wrong. If any comparison is meaningful at all, it must be like "<A> is better than <B> in the particular case <C>", i.e. you must specify the use-case first. Furthermore, most mechanisms of SW development have advantages and disadvantages (or call it pros and cons) whenever you compare two of these. So actually I suggest to use statements like "<A> has advantage <D> in comparison with <B> in the particular case <C>".

As for examples, I believe OO concepts are applicable for a systems of code. I mean not just some specific calculations or one-two specific features. The OO concepts start to shine, when you are at a point that you need more than one developer to implement and maintain the software. So any example of less than one million lines of code isn't adequate to demonstrate the idea and the power of a concept. Examples of few hundreds of lines demonstrate the syntax and the mechanics, may be show some properties of a particular approach. However, there are a lot of advises in different books (based on heuristics, experience and conceptual work).

Inheritance over Composition

Typical use of inheritance appears in GUI frameworks. Often there is a common base class like Object or Control. Other classes inherit few common properties and extend the modeled object by further properties like size or visible.

In this case the inheritance has following advantages over composition:

The charm of this approach is that you (as the framework developer) can create relatively fast and cheap seemingly extensive framework. Instead of a sophisticated hierarchy you basically create some general classes like Window, Frame and Control, inherit from a base class Object a set of interface methods for every leaf object like OpenFileDialog or TextControl and basically pretend unlimited flexibility. The flexibility and extensibility is practically zero for such an approach, but the customer (poor developer who has to implement some colorful features) will notice it after he has payed for a 5 years license.

A subjective example for an inheritance-oriented GUI framework prototype is .NET. It contains everything you need to develop Visual Studio, but it lacks a lot of basic functionality and displays incompatibility and bad design if you try to create extensive GUI that should have different look-and-feel compared to Visual Studio.

Another subjective example is wxWidgets framework, which shows better coverage of basic functionality and a well thought-out architecture design. However, due to big number of access methods and extremely thick interfaces (at least in my opinion) it appears hard to find the wanted methods. Though one must say wxWidgets isn't pure inheritance-oriented, it rather combines thought-out inheritance hierarchy with flexible composition mechanisms, which together allow nearly unlimited combinations of framework objects.

One more subjective example are java's GUI frameworks like AWT, Swing and SWT. These frameworks carry out the very idea of inheritance to its extents. However, every time I am forced to use these I consider these frameworks as a big failure. It appears like these frameworks inherited the bad design and architecture of .NET and thick interfaces from wxWidgets, but dropped everything that could be of any use.

Composition over Inheritance

Typical use of composition appears in relatively small modules and packages that handle a specific topic like data management (stack, vector, hash-map, xml-dom), string management (search, concatenation, transformation), file management (open, read, write, close). Such a modules and packages contain a handful classes that have no inheritance relations to each other, but require or provide interfaces built on the definitions of other classes.

In these cases the composition has following advantages over inheritance:

Conclusion

I cannot prefer one method to other in general and I definitely don't want to miss any of these methods, since the usefulness depends on the use case. A greenhorn might consider these methods concurrent, while the professional will achieve the optimum combining composition and inheritance (look closely at DesignPatterns). -- SergejPauls 20131031


See Also: LimitsOfHierarchies DelegationAndConsultation


CategoryPolymorphism


EditText of this page (last edited October 31, 2013) or FindPage with title or text search