13

This page advocates composition over inheritance with the following argument (rephrased it in my words):

A change in the signature of a method of the superclass (which hasn't been overridden in the subclass) causes additional changes in many places when we use Inheritance. However, when we use Composition, the required additional change is only at a single place: The subclass.

Is that really the only reason to favor composition over inheritance? Because if that's the case, this problem can be easily alleviated by enforcing a coding style which advocates overriding all methods of the superclass, even if the subclass does not change the implementation (that is, putting dummy overrides in the subclass). Am I missing something here?

4
  • 3
    Possible duplicate of Why should I prefer composition over inheritance?
    – gnat
    May 24, 2017 at 14:12
  • 1
    see also: Discuss this ${blog}
    – gnat
    May 24, 2017 at 14:14
  • 2
    The quote doesn't say it is "the only" reason. May 24, 2017 at 14:30
  • 3
    Composition is almost always better, because inheritance generally adds complexity, coupling, code reading, and reduces flexibility. But there are notable exceptions, sometimes a base class or two doesn't hurt. That's why its 'prefer' rather than 'always'. May 24, 2017 at 19:59

8 Answers 8

28

I like analogies so here's one: Have you ever seen one of those TVs that had a VCR player built-in? How about the one with a VCR and a DVD player? Or one that have a Blu-ray, DVD and VCR. Oh and now everyone is streaming so we need to design a new TV set...

Most likely, if you own a TV set, you don't have one like the above. Probably most of those have never even existed. You most likely have a monitor or set that has numerous inputs so that you don't need a new set every time there is a new type of input device.

Inheritance is like the TV with the VCR built-in. If you have 3 different types behaviors you want to use together and each has 2 options for implementation, you need 8 different classes in order to represent all of those. As you add more options the numbers explode. If you use composition instead, you avoid that combinatorial problem and the design will tend to be more extensible.

8
  • 6
    There were plenty of TVs with VCR and DVD players built in in the late 90s and early 2000s.
    – JAB
    May 24, 2017 at 18:39
  • @JAB and many (most?) TVs sold today support streaming, for that matter.
    – Casey
    May 24, 2017 at 18:58
  • 4
    @JAB And none of them can have their DVD player sold to help buy a Bluray player
    – Alexander
    May 24, 2017 at 20:07
  • 1
    @JAB Right. The statement "Have you ever seen one of those TVs that had a VCR player built-in?" implies they exist.
    – JimmyJames
    May 24, 2017 at 20:09
  • 4
    @Casey Because obviously, there will never be another technology that will supersede this one, right? I'll wager that any of those TVs also support inputs from external devices just in case someone wants to use something else without buying a new TV. Or rather, few educated buyers are willing to purchase a TV that lacks such inputs. My premise isn't that these approaches don't exist and neither would I claim inheritance doesn't exist. The point is that such approaches are inherently less flexible than composition.
    – JimmyJames
    May 24, 2017 at 20:13
4

Normally the driving idea of Composition-Over-Inheritance is to provide greater design flexibility and not to reduce the quantity of code you need to change to propagate a change (that I find questionable).

The example on wikipedia give a better example of the power of his approach:

Defining a base interface for each "composition-piece" you could easy create various "composed-object" with a variety that could be difficult to reach with inheritance alone.

2
  • So this section gives a Composition example, right? I am asking because it is not obvious in the article.
    – Utku
    May 24, 2017 at 13:41
  • 1
    Yes, "Composition over inheritance" doesn't mean you don't have interfaces, if you look at the Player object you can see that fit nicely in a hierachy, but at the (excuse the brutalilty) code is not coming from inheritance, but from the composition with some class that does the work
    – lbenini
    May 24, 2017 at 13:46
4

No, it is not. In my experience composition over inheritance is a result of thinking about your software as a bunch of objects with behaviours that talk to each other / objects providing services to each other instead of classes and data.

This way, you have some objects that provide serviecs. You use them as building blocks (really pretty much like Lego) to enable other behaviour (e.g. a UserRegistrationService uses the services provided by an EmailerService and a UserRepository).

When building larger systems with this approach i naturally used inheritance in very few cases. At the end of the day inheritance is a very powerful tool that should be used with caution and only where appropriate.

7
  • I see the Java mentality here. OOP is about the data being packaged together with the functions that act on it - what you're describing is better termed "modules". You're right in that avoiding inheritance is a good idea when you're repurposing objects as modules, but I find it disturbing that you seem to be recommending that as the preferred way of using objects.
    – Brilliand
    May 24, 2017 at 18:47
  • 1
    @Brilliand If you only knew how much java code is written in the style as you describe and how much of a horror this is... Smalltalk introduced the term OOP and it was designed around objects receiving messages.: "Computing should be viewed as an intrinsic capability of objects that can be uniformly invoked by sending messages." There is no mention of data and functions operating on it. Sorry, but in my opinion you are gravely mistaken. If it were just about data and functions one could happily continue writing structs.
    – marstato
    May 24, 2017 at 20:11
  • @Tsar unfortunately, even though Java supports static methods, the Java culture does not
    – k_g
    May 25, 2017 at 0:56
  • @Brilliand Who cares what OOP is "about"? What matters is how you can use it and the results of using it in those ways.
    – user253751
    May 25, 2017 at 3:33
  • 1
    After discussion with @Tsar: Java classes do not have to be instantiated, and indeed, classes such as UserRegistrationService and EmailService should usually not be instantiated - classes with no associated data work best as static classes (and as such, are irrelevant to the original question). I'll be deleting some of my previous comments, but my original criticism of marsato's answer stands.
    – Brilliand
    May 25, 2017 at 20:40
4

"Prefer composition over inheritance" is just a good heuristic

You should consider the context, as this is not a universal rule. Do not take it to mean never use inheritance when you can do composition. If that were the case, you would fix it by banning inheritance.

I hope to make this point cleared along this post.

I will not try to defend the merits of composition by itself. Which I consider off topic. Instead, I will talk about some situations when developer may consider inheritance that would be better using composition. On that note, inheritance has its own merits, which I also consider off topic.


Vehicle example

I am writing about developers who tries to things the dumb way, for narrative purposes

Let us go for a variant of the classical examples that some OOP courses use… We have a Vehicle class, then we derive Car, Airplane, Balloon and Ship.

Note: If you need to ground this example, pretend these are kinds of objects in a video game.

Then Car and Airplane may have some common code, because they both can roll on wheel on land. The developers may consider creating an intermediary class in the inheritance chain for that. Yet, actually there is also some shared code between Airplane and Balloon. They could consider creating another intermediary class in the inheritance chain for that.

Thus, the developer would be looking for multiple inheritance. At the point where the developers are looking for multiple inheritance, the design has already gone wrong.

It is better to model this behavior as interfaces and composition, so we can reuse it without having to run into multiple class inheritance. If the developers, for example, create the FlyingVehicule class. They would be saying that Airplane is a FlyingVehicule (class inheritance), but we could instead say that Airplane has a Flying component (composition) and Airplane is a IFlyingVehicule (interface inheritance).

Using interfaces, if necessary, we can have multiple inheritance (of interfaces). In addition, you are not coupling to a particular implementation. Increasing reusability and testability of your code.

Remember that inheritance is a tool for polymorphism. In addition, polymorphism is a tool for reusability. If you can increase the reusability of your code by using composition, then do so. If you are not sure whatever or not composition provides better reusability, "Prefer composition over inheritance" is a good heuristic.

All that without mentioning Amphibious.

In fact, we may not need things that go off the ground. Stephen Hurn has a more eloquent example in his articles “Favor Composition Over Inheritance” part 1 and part 2.


Substitutability and Encapsulation

Should A inherit or compose B?

If A Is an specialization of B that should fulfil the Liskov substitution principle, inheritance is viable, even desirable. If there are situations where A is not a valid substitution for B then we should not use inheritance.

We might be interested in composition as a form of defensive programming, to defend the derived class. In particular, once you start using B for other different purposes, there may be pressure to change or extend it to be more suitable for those purposes. If there is the risk that B may expose methods that could result in an invalid state in A we should be using composition instead of inheritance. Even if we are the author of both B and A, it is one thing less to worry about, therefore composition eases the reusability of B.

We may even argue that if there are features in B that A does not need (and we do not know if those features could result in an invalid state for A, either in the present implementation or in the future), it is a good idea to use composition instead of inheritance.

Composition also has the advantages of allowing switching implementations, and easing mocking.

Note: there are situations where we want to use composition despite the substitution being valid. We archive that substitutability by using interfaces or abstract classes (which one to use when is another topic) and then use composition with dependency injection of the real implementation.

Finally, of course, there is the argument that we should use composition to defend the parent class because inheritance breaks the encapsulation of the parent class:

Inheritance exposes a subclass to details of its parent's implementation, it's often said that 'inheritance breaks encapsulation'

-- Design Patterns: Elements of Reusable Object-Oriented Software, Gang of Four

Well, that is a poorly designed parent class. Which is why you should:

Design for inheritance, or prohibit it.

-- Effective Java, Josh Bloch


Yo-Yo problem

Another case where composition helps is the Yo-Yo problem. This is a quote from Wikipedia:

In software development, the yo-yo problem is an anti-pattern that occurs when a programmer has to read and understand a program whose inheritance graph is so long and complicated that the programmer has to keep flipping between many different class definitions in order to follow the control flow of the program.

You can resolve, for example: Your class C will not inherit from class B. Instead your class C will have a member of type A, which may or may not be (or have) an object of type B. This way you will not be programming against the implementation detail of B, but against the contract that the interface (of) A offers.


Counter examples

Many frameworks favor inheritance over composition (which is the opposite of what we have been arguing). Developer may do this because they put a lot of work into their base class that having it implemented with composition would have increase the size of the client code. Sometimes this is due to limitations of the language.

For example, a PHP ORM framework may create a base class that uses magic methods to allow writing code as if the object had real properties. Instead the code handled by the magic methods will be going to the database, query for the particular requested field (perhaps cache it for future request) and return it. Doing it with composition would require the client to either create properties for each field or write some version of the magic methods code.

Addendum: There some other ways one could allow extending ORM objects. Thus, I do not think inheritance is necessary on this case. It is cheaper.

For another example, a video game engine may create a base class that uses native code depending on the target platform to do 3D rendering and event handling. This code is complex and platform specific. It would be expensive and error prone for the developer user of the engine to deal with this code, in fact, that is part of the reason of using the engine.

Furthermore, without the 3D rendering part, this is how many widget frameworks work. This releases you from worrying about handling OS messages… in fact, in many languages you cannot write such code without some form of native biding. Moreover, if you were to do it, it would tight your portability. Instead, with inheritance, provided the developer do not break compatibility (too much); you will be able to easily port your code to any new platforms they support in the future.

In addition, consider that many times we only want to override a few methods and leave everything else with the default implementations. Had we been using composition we would have to create all those methods, even if only to delegate to the wrapped object.

By this argument, there is a point where composition can be worst for maintainability than inheritance (when the base class is too complex). Yet, remember that maintainability of inheritance can be worse than that of composition (when the inheritance tree is too complex), which is what I refer to in the yo-yo problem.

In the presented examples, the developers rarely intend to reuse the code generated via inheritance in other projects. That mitigates the diminished reusability of using inheritance instead of composition. In addition, by using inheritance the framework developers can provide a lot of easy to use and easy to discover code.


Final thoughts

As you can see, composition has some advantage over inheritance in some situations, not always. It is important to consider the context and the different factors involved (such as reusability, maintainability, testability, etc…) to make the decision. Back to the first point: "Prefer composition over inheritance" is a just good heuristic.

You may also have notices that many of the situation I describe can be resolved with Traits or Mixins to some degree. Sadly, these are not common features in the great list of languages, and they usually come with some performance cost. Thankfully, their popular cousin Extension Methods and Default Implementations mitigate some situations.

I have a recent post where I talk about some of the advantages of interfaces in why do we require interfaces between UI,Business and Data access in C#. It helps decoupling and eases reusability and testability, you might be interested.

4
  • Uh... .Net framework uses several types of inherited streams to do it's stream-related work. It works incredibly well and it is super easy to use and extend. Your example isn't a very good one...
    – T. Sar
    May 24, 2017 at 23:16
  • 1
    @TSar "it is super easy to use and extend" Have you ever tried to tee the standard out stream to Debug? That's been my only experience trying to extend their streams. It was not easy. It was a nightmare that ended in me overriding every single method in the class explicitly. Extremely repetitive. And if you look at the .NET source code, overriding everything explicitly is pretty much how they do it. So I'm not convinced it's ever that easy to extend.
    – jpmc26
    May 24, 2017 at 23:51
  • Reading and writing a struct from a stream is better done with free functions, or multimethods.
    – user253751
    May 25, 2017 at 3:34
  • @jpmc26 I'm sorry your experience wasn't very good. I had no issues myself using or implementing stream-related stuff for different things, however.
    – T. Sar
    May 25, 2017 at 6:48
3

The line: "Prefer composition over inheritance" is nothing but a nudge in the right direction. It's not going to save you from your own stupidity and actually gives you a chance to make things much worse. That's because there is a lot of power here.

The main reason this even needs to be said is because programmers are lazy. So lazy they will take any solution that means less keyboard typing. That is the main selling point of inheritance. I type less today and some someone else gets screwed tomorrow. So what, I wanna go home.

Next day the boss insists I use composition. Doesn't explain why but is insisting on it. So I take an instance of what I was inheriting from, expose an interface identical to what I was inheriting from, and implement that interface by delegating all work to that thing I was inheriting from. It's all brain dead typing that could have been done with a refactoring tool and seems pointless to me but the boss wanted it so I do it.

Next day I ask if this is what was wanted. What do you think the boss says?

Unless there was some need to be able to dynamically (at run time) change what was being inherited from (see state pattern) this was a huge waste of time. How can the boss say that and still be in favor of composition over inheritance?

In addition to this not doing a thing to prevent breakage due to method signature changes this entirely misses the biggest advantage of composition. Unlike inheritance you are free to make a different interface. One more appropriate to how it'll be used at this level. You know, abstraction!

There are some minor advantages to automatically replacing inheritance with composition and delegation (and some disadvantages) but keeping your brain turned off during this process is missing a huge opportunity.

Indirection is very powerful. Use it wisely.

0

Here is another reason: in many OO languages (I am thinking of ones like C++, C# or Java here), there is no way to change the class of an object once you've created it.

Suppose we're creating an employee database. We have an abstract base Employee class, and start to derive new classes for specific roles - Engineer, Security Guard, Truck Driver and so on. Each class has specialised behaviour for that role. Everything is good.

Then one day an Engineer gets promoted to Engineering Manager. You can't re-class an existing Engineer. Instead, you have to write a function that creates an Engineering Manager, copying all the data from the Engineer, deletes the Engineer from the database, then adds the new Engineering Manager. And you have to write such a function for each possible role change.

Even worse, suppose a Truck Driver goes on long-term sick leave, and a Security Guard offers to do Truck Driving part time to fill in. You now have to invent a new Security Guard And Truck Driver class just for them.

It makes life so much easier to create a concrete Employee class, and treat it as a container to which you can add properties, such as the job role.

1
  • Or you create a Employee class with a pointer to a List of Roles, and each actual job extends Role. Your example could be made to use inheritance in a very good and sensible way without too much work.
    – T. Sar
    May 24, 2017 at 23:21
0

Inheritance provides two things:

1) Code-reuse: Can be accomplished easily through composition. And in fact, is better achieved through composition as it better preserves encapsulation.

2) Polymorphism: Can be accomplished through "interfaces" (classes where all methods are pure-virtual).

A strong argument for using non-interface inheritance, is when the number of methods required is large and your subclass only wants to alter a small subset of them. However, in general your interface's should have very small footprints if you subscribe to the "single-responsibility" principle (you should), so these cases should be rare.

Having the coding style requiring overriding all parent class methods doesn't avoid writing a large number of pass-through methods anyways, so why not re-use code through composition and get the added benefit of encapsulation? Plus, if the super-class were to be extended by adding another method, the coding style would require adding that method to all sub-classes (and there's a good chance we're then violating "interface segregation"). This problem grows quickly when you start having multiple levels in inheritance.

Finally, in many languages unit testing "composition" based objects is much easier than unit testing "inheritance" based objects by substituting the member object with a mock/test/dummy object.

0

Is that really the only reason to favor composition over inheritance?

Nope.

There are many reasons to favor composition over inheritance. There isn't a single correct answer. But I'll throw another reason to favor composition over inheritance into the mix:

Favoring composition over inheritance improves the readability of your code, which is very important when working on a large project with multiple people.

Here's how I think about it: when I'm reading somebody else's code, if I see that they've extended a class, I'm going to ask what behavior in the super class are they changing?

And then I'll go through their code, looking for an overriden function. If I don't see any, then I classify that as a misuse of inheritance. They should have used composition instead, if only to save me (and every other person on the team) from 5 minutes of reading through their code!

Here's a concrete example: in Java the JFrame class represents a window. To create a window, you create an instance of JFrame and then call functions on that instance to add stuff to it and show it.

Many tutorials (even the official ones) recommend that you extend JFrame so you can treat instances of your class as instances of JFrame. But imho (and the opinion of many others) is that this is a pretty bad habit to get into! Instead, you should just create an instance of JFrame and call functions on that instance. There is absolutely no need to extend JFrame in this instance, since you aren't changing any of the default behavior of the parent class.

On the other hand, one way to perform custom painting is to extend the JPanel class and override the paintComponent() function. This is a fine use of inheritance. If I'm looking through your code and I see that you've extended JPanel and overrided the paintComponent() function, I'll know exactly what behavior you're changing.

If it's just you writing code by yourself, then it might be just as easy to use inheritance as it is to use composition. But pretend you're in a group environment and that other people will be reading your code. Favoring composition over inheritance makes your code easier to read.

14
  • Adding an entire factory class with a single method that returns an instance of an object so you can use composition instead of inheritance doesn't really make your code more readable... (Yes, you need this if you need a new instance each time a particular method is called.) That doesn't mean inheritance is good, but composition doesn't always improve readability.
    – jpmc26
    May 24, 2017 at 23:12
  • 1
    @jpmc26 ...why on earth would you need a factory class just to create a new instance of a class? And how does inheritance improve the readability of what you're describing? May 24, 2017 at 23:21
  • Did I not explicitly give you a reason for such a factory in the comment above? It's more readable because it results in less code to read. You can accomplish the same behavior with a single abstract method in the base class and a few subclasses. (You were going to have a different implementation of your composed class for each one, anyway.) If the details of constructing the object are strongly tied to the base class, it won't find much use anywhere else in your code, further reducing the benefits of making a separate class. Then it keeps closely related parts of code near each other.
    – jpmc26
    May 24, 2017 at 23:35
  • As I said, this doesn't necessarily mean inheritance is good, but it does exemplify how composition doesn't improve readability in some situations.
    – jpmc26
    May 24, 2017 at 23:37
  • 1
    Without seeing a specific example, it's hard to really comment. But what you've described sounds like a case of over-engineering to me. Need an instance of a class? The new keyword gives you one. Anyway thanks for the discussion. May 24, 2017 at 23:41

Not the answer you're looking for? Browse other questions tagged or ask your own question.