41

I keep hearing the phrase "Favour Composition over Inheritance" from GoF, which is being annoyingly mentioned repeatedly by my friend, who thinks it is a valid blanket statement. But is it not more sensible to consider that the real reason why inheritance exists is not just for behaviour reuse, but for the case where a hierarchy of classes inheriting from the same ancestor need to be passed as arguments to a function? That is: to implicitly implement polymorphism, and these descendent classes have methods which are polymorphisms of a funtion in the ancestral class. Use of inheritance in this manner is the sole reason why herds and fleets of programmers find it pleasurable to write UI with Microsoft's WPF with (Visual) C#. How would composition fit nicely into the picture of UI framework design, without being too verbose?

I know compatibility clashes may arise from the usage of inheritance, which is one of the things the statement aims to protect one from, but is it not a question of bad design on the programmer's part (failure to discern when to inherit and when to compose) rather than on the paradigm or language?

P.S.: I used the terms ancestor and descendent to avoid implying inheritance depth through the usage of parent and child.

6
  • There is the aspect of taking the parent and child classes as arguments where the parameter is the parent. (That is the difference between this question and the possible duplicate). The contexts of the two questions are different enough to elicit two distinct sets of answers - there is no answer to my question on that question. Oct 18, 2014 at 22:23
  • 1
    Inheritance not generally viewed as bad. Just overused / misused.
    – codenheim
    Oct 18, 2014 at 22:29
  • @RonaldMunodawafa Passing a child instance in place of a parent instance is just run of the mill subtyping, which can equally easily be achieved via interfaces.
    – user7043
    Oct 18, 2014 at 22:56
  • @delnan, you have implicitly unintentionally rules Python off as a run off the mill language Oct 18, 2014 at 23:03
  • 1
    This is why I think implementation inheritance is bad, while subtyping is good: yegor256.com/2016/09/13/inheritance-is-procedural.html
    – yegor256
    Sep 13, 2016 at 17:17

2 Answers 2

50

You ask why, as if the whether is decided. Lets consider your supposition:

Why is inheritance generally viewed as a bad thing by OOP proponents

I disagree with the premise of the question. Inheritance isn't generally viewed as bad, it is viewed as misused and overused.

GoF Design Patterns says no such thing about it being bad.

Let's see what GoF Design Patterns actually says...

  1. p20 - In the discussion of Favor composition over inheritance, that Inheritance and object composition thus work together.
  2. p22 - Object composition lets you change the behavior being composed at run-time, but it also requires indirection and can be less efficient.
  3. p25 - ... on the other hand, heavy use of object composition can make designs harder to understand.

And so on. Now, there are also plenty of downsides to inheritance that I could quote, but the point is, GoF doesn't claim inheritance is bad, and clearly teaches the pros and cons of various techniques. What does favour mean in this context? Don't make inheritance your first choice. Kinda like don't make the crowbar your first choice, try the key first.

As far as inheritance, there are two major types, Class inheritance and Interface inheritance (subtyping). Both are appropriate for particular patterns but the latter has come into favor since GoF was published. If you were learning OOP back in the early 90s, you would know about Booch Method and Rumbaugh Method, but nowadays you hear little of those. Yet they were teaching a generation of C++ (and Java) programmers to inherit and override. But state of the art has moved on. We have, through collective experience, found that loose coupling is really found through use of interfaces and dependency injection, and not merely by using encapsulation.

The problem with inheritance is too many "OO" programmers think of problems first as potential inheritance solutions. Inheritance is a concrete concept that people understand quickly early on, so many latch onto that and never really grow much more as system modelers. When everything in a system is wedged into an inheritance hierarchy, and code is reused by class inheritance, it makes for some disastrous results and the benefits of OO are outweighed by actually wrestling with the hierarchy itself. I've seen many projects, and been responsible for some myself, that spent more time wrestling a huge hierarchy than actually maintaining the sub-system interfaces. This is a sign of inheritance misuse.

But that aside, inheritance is invaluable for accomplishing many good things. Polymorphism (specifically sub-type polymorphism) is a very powerful tool and single and double dispatch are key for patterns such as Visitor pattern. Interface inheritance is key to designing to interfaces, not implementations. Abstract classes or interfaces are only useful with inheritance.

If your friend thinks that "favour composition over inheritance" is a mantra for avoiding inheritance altogether, he is mistaken and doesn't understand the concept of a complete toolset.

Sounds as if he hasn't actually read GoF. If he did claim to read it, then it sounds as if he misunderstood it and should read it again.

4
  • I am designing a UI framework (basically an API to HTML5 + CSS + JavaScript for .NET) that pretty much depends on inheritance hierarchies, polymorphism and composition and he keeps on telling me to read GoF (though I now doubt he has read it at all) telling me inheritance is bad but nw I have somehting to hold him by. Oct 19, 2014 at 7:32
  • 1
    GUI frameworks are a domain where inheritance often actually is the best technique.
    – codenheim
    Oct 19, 2014 at 7:34
  • 1
    Exactly, @codenheim! Anyone who denounces that fact is mistaken. Oct 19, 2014 at 8:43
  • I don't disagree, but do you have a citation or data to indicate the reliability of that fact @RonaldMunodawafa?
    – rayhem
    Jul 31 at 20:20
11

...my friend who thinks it is a valid blanket statement but is it not more sensible to...

Yes, it is always more sensible (time permitting) to understand why things are the way they are rather than following some mantra blindly.

real reason why inheritance exists is not just for behaviour reuse but for the case where a hierarchy of classes inheriting from the same ancestor need to be passed as arguments to a function

Not correct. That is an implementation detail of languages, and while a fairly significant one - not what you should focus on.

to implicitly implement polymorphism and these descendent classes have methods which are polymorphisms of a funtion in the ancestral class.

And that too is not quite correct.

is it not a question of bad design on the programmer's part (failure to discern when to inherit and when to compose) rather than on the paradigm or language?

It entirely is a question of bad design on the programmer's part. The general disdain for inheritance isn't for inheritance the concept, it's for inheritance being used in code that causes pain.

Because inheritance (and all subtyping) is a specialization of some super-type. Not just that, but well done inheritance is a specialization of the contracts defined by the super type (else the whole Rectangle/Square thing would actually work). Even when programmers know that they're supposed to do that (and very few do). It's hard to refine the contracts of the type without breaking other parts of the contracts (see the Width/Height behaviors in Rectangle/Square for an example). And worse yet, it's not particularly common that you want to actually do that limited specialization since it rarely is useful.

So instead, there's a boatload of programmers misusing inheritance, just to do polymorphism, or to have XY and Z (tacking on an extra field is a fragile and often dangerous use of inheritance), or to kinda sorta specialize things (yes, Penguin is a Bird, but it's .Fly() method doesn't work...), or...

So inheritance is viewed as a generally bad thing since it generally yields bad results.

2
  • Why is the implementation detail of a language not what I should focus given that you are assuming why I am asking these questions. Oct 19, 2014 at 8:38
  • 1
    @RonaldMunodawafa - Because beginners tend to think of things in terms of their programming language (how to do things) rather than in terms of concepts (how things interact). The latter is far more useful, because while languages change and evolve, the concepts largely don't. Better yet, thinking of things at a higher level than implementation details lets you work across larger problems more efficiently.
    – Telastyn
    Oct 19, 2014 at 12:59

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