I have a set of classes that are all dealing with some related tasks. These tasks do have different inputs and outputs. This causes it to become impossible to have the tasks done via shared code without having this code be a pile of if-else statements handling all the different cases.

Now someone refactored this code to use inheritance - there now is an abstract base class that holds methods for each of which it is used by some of the deriving classes, for some of which they get overridden or nullified and some of which are always called though not always applicable for the deriving class. Furthermore the inheritance is not used for polymorphism at all, just code reuse.

I cringed a bit when I noticed this refactoring was done and that it happily got through code review. The codebase I am working with has existed for quite a while and is full of these kind of things, and most people don't understand the issues. I'm thus looking for a good overview of why inheritance should not be abused like this, esp including all the problems it causes.

  • Were methods ever duplicated before? Did you have 'copy-pasted' functionality? – MrFox Feb 21 '13 at 15:53

The keyword (or phrase) to search for here is composition over inheritance. It's a popular design guideline and you can find a general introduction at wikipedia.

Additionally, there is a community question here which provides you with a huge number of arguments on when to prefer CoI. As indicated by several (and highly valued) answers, the basic guideline for deciding between composition and inheritance is the Liskov substitution principle, which should be adhered to when using inheritance.

| improve this answer | |
  • 1
    To give a slightly different viewpoint: Code-reuse through inheritance is not a problem if private inheritance was used, because then the Liskov substiturion principle does not apply. This assumes of course that the language in question supports private inheritance. – Bart van Ingen Schenau Feb 21 '13 at 14:42
  • @BartvanIngenSchenau total agreement, and I'd like to add that this is one of those points where the language in question matters. I find that Java is much more "composition over inheritance" than let's say python or C++. – MrFox Feb 21 '13 at 15:52
  • @MrFox To be clear, you're referring to multiple inheritance, correct? I'd also add that even abstracts or interfaces can present problems as well, if like me you've ever had to use an API where in order to get to IWheel you first have to cast IEngine to ICar (paraphrasing). How things got that bad is a long story involving contractors, don't let it happen to you! – jzx Feb 21 '13 at 16:26
  • @BartvanIngenSchenau: Could you elaborate more about why private inheritance work? – Niing Apr 2 '19 at 17:02
  • 1
    @Niing: In private inheritance, there is no (automatic, implicit) conversion from derived class to base class. This means that you can't pass an inappropriate derived class to a function that expects a base class. – Bart van Ingen Schenau Apr 2 '19 at 17:24

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