11

I'm trying to teach myself software engineering and coming up against some conflicting information which is confusing me.

I've been learning OOP and what abstract classes / Interfaces are and how to use them, but then I'm reading that one should 'favour composition over inheritance'. I understand composition is when one class composes / creates an object of another class to utilise / interact with that new object's functionality.

So my question is... Am I supposed to not use abstract classes and interfaces? To not create an abstract class and extend / inherit that abstract class's functionality in the concrete classes, and instead, just compose new objects to use the other class's functionality?

Or, am I supposed to use composition AND inherit from abstract classes; using them both in conjunction with each other? If so, could you provide some examples of how that would work and its benefits?

As I'm most comfortable with PHP, I'm using it to improve my OOP / SE skills before moving on to other languages and transferring my newly acquired SE skills, so examples using PHP would be most appreciated.

  • 2
    "Favor composition over inheritance" is a silly idea that makes exactly as much sense as "favor saws over drills." They're two different tools that are appropriate to use in two different use cases, and the times when you can really use either one interchangeably are actually pretty rare. – Mason Wheeler Nov 8 '15 at 17:08
  • 2
    "Favour X over Y" doesn't mean never use Y, just think about if X would be better – Richard Tingle Nov 8 '15 at 22:37
  • 2
    "Favour composition over inheritance" is more accurately expressed as "Never, ever, ever use class inheritance", with the clarification that implementing an interface is not inheritance and if your chosen language only supports abstract classes, not interfaces, inheriting from a 100% abstract class can be viewed as "not inheritance" as well. – David Arno Jan 20 '16 at 11:21
  • 1
    @MasonWheeler, there are no valid use-cases for inheritance. It's at least as "evil" a feature as "goto". – David Arno Jan 20 '16 at 11:22
  • 1
    @DavidArno That's just plain ridiculous. Inheritance is one of the most useful, productive features ever developed in the entire history of programming. As with anything useful, there are plenty of ways to abuse it, but used properly it massively increases the power and productivity of your work. – Mason Wheeler Jan 20 '16 at 12:04
18

Composition over Inheritance means that when you want to re-use or extend functionality of an existing class, often it's more appropriate to create another class that will 'wrap' the existing class and use it's implementation internally. Decorator pattern is an example of this.

Inheritance isn't a good default way to deal with re-use scenarios because you often want to use just a part of a base class funtionality and the subclass can't support the whole contract of the base class in a way that satisfies Liskov substitution principle.

Template method is a good example of a case where inheritance is appropriate.

See this answer for guidelines on how to choose between composition and inheritance.

  • +1 for pointing out that in the case of partial reuse of a class, the unused portion is more cleanly ignored with composition than with inheritance. – Lawrence Nov 8 '15 at 6:38
4

I'm not familiar enough with PHP to give you concrete examples in that language, but here are a few guidelines that I have found useful.

Interfaces/traits are useful for defining behavior across many classes that may have very little else in common.

For example, if you are working on a JSON api, you may define an interface that specifies two methods: “toJson” and “toStatusCode”. This would allow you to write a helper that can take any object that implements this interface, and convert it into an Http response.

Most of the time, this is preferable to direct inheritance, because it's less likely to suffer from the fragile base class problem, as it tends toward shallow class hierarchies.

Direct Inheritance is best thought of as something you do when there are compelling reasons to do so, rather than something you do unless there are compelling reasons not to.

In languages that do not support default implementations in interfaces, it may be a reasonable way to share a set of base functionality, but it usually heavily restricts what you can do with the subclasses (multiple inheritance, when available, is rarely worth the pain). Often, I find it's worth the pain of writing the boilerplate redirect methods to use composition instead.

Composition should be your default strategy. As much as possible, compose with interfaces, and pass them in as constructor arguments. This will make your life much easier when writing tests.

Avoid working with global singletons as much as possible, as comparing expected and actual output is a right pain if part of the output depends on the state of the system clock.

This is, of course, not always possible. For example, the Play web framework provides a JSON library that's basically a domain specific language. Changing this would be a major undertaking, of which, replacing the calls to 'Json.prettyPrint' would be only a very minor part.

1

Composition is when a class offers some functionality by instantiating a (possibly internal) class which already implements this functionality, instead of inheriting from that class.

So, for example, if you have a class which models a ship, and you are now being told that your ship should offer a helipad, it is not natural to derive your ship from a helipad, (duh!) instead, you should have your ship contain a helipad class and expose it via some Ship.getHelipad() method.

In years of old (a decade or so ago) people used to view inheritance as a quick and easy way to aggregate functionality, so there were many examples of the "ship inheriting from helipad" kind, which were, of course, very lame.

But the "Favor Composition over Inheritance" dictum has been carefully worded as to make it clear that this is just a suggestion, not a rule. The author of the dictum was careful enough to refrain from saying something like "thou shalt never use inheritance, only composition". This is basically bringing to the attention of the software engineering community the fact that inheritance has been overused, while in many cases, composition produces more clear, elegant, and maintainable designs than inheritance.

So, essentially, the "Favor Composition over Inheritance" dictum is suggesting that whenever you are faced with the "to inherit or to compose?" question, you should think hard what's the most suitable strategy, and that most chances are that the most suitable strategy will turn out to be composition, not inheritance.

But since this is not a rule, you should also keep in mind that there are many cases where inheritance is more natural. If you use composition there where you should have used inheritance, many evils will befall your code.

To go back to the ship example, if your ship needs to offer an interface for interacting with a FloatingMachine, then it is more natural to derive it from an abstract FloatingMachine class, which might very possibly in turn be derived from another abstract Machine class.

Here is the rule of thumb for the answer to the composition vs. inheritance question:

Does my class have an "is a" relationship to the interface that it needs to expose? If yes, use inheritance. If not, use composition.

A ship "is a" floating machine, and a floating machine "is a" machine. So, inheritance is perfectly fine for those. But a ship is not, of course, a helipad. So it better compose the functionality of the helipad.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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