Inheritance or composition: Rely on "is-a" and "has-a"?

Yes and no.

The line can be blurred. This hasn't been helped by some pretty terrible examples of OO programming from the early days of OO like: Manager is an Employee is a Person.

The thing you have to remember about inheritance is: inheritance breaks encapsulation. Inheritance is an implementation detail. There's all sorts written on this subject.

The pithiest way to sum it up is:

Prefer composition.

That doesn't mean use it to the complete exclusion of inheritance. It just means inheritance is a fallback position.


No - "is a" does not always lead to inheritence. A well cited example is the relationship between a square and a rectangle. A square is a rectangle, but it will be bad to design code that inherits a Square class off a Rectangle class.

My suggestion is to enhance your "is a / has a" heuristic with the Liskov Substitution Principle. To check whether an inheritence relationship complies with the Liskov Substitution Principle, ask whether clients of a base class can operate on the sub class without knowing that it is operating on a sub class. Of course, all the properties of the sub class must be preserved.

In the square / rectangle example, we must ask whether a client of rectangle can operate on a square without knowing that it is a square. All that the client must know is that it is operating on a rectangle. The following function demonstrates a client that assumes that setting the width of a rectangle leaves the height unchanged.

void g(Rectangle& r)
{
    r.SetWidth(5);
    r.SetHeight(4);
    assert(r.GetWidth() * r.GetHeight()) == 20);
}

This assumption is true for a rectangle, but not for a square. So the function cannot operate on a square and therefore the inheritence relationship violates the Liskov Substitution principle.

Other examples


If the relationship is "is-a" - use inheritance, and if the relationship is "has-a" - use composition. Is it always right?

In a sense, yes. But you must be careful not to introduce unnecessary, artificial "is-a" relationships.

For example, one may think that a ThickBorderedRectangle is-a Rectangle, which seems reasonable at first sight, and decide to use inheritance. But this situation is better described saying that a Rectangle has-a Border, which may or may not be a ThickBorder. In this case he would better prefer composition.

In the same fashion, one may think that a ThickBorder is-a special Border and use inheritance; but it's better to say that a Border has-a width, hence preferring composition.

In all these ambiguous cases, my rules of thumb are think twice and, as others advised, prefer composition over inheritance.