Blog 3 min read

OOP vs Generics: "Is" vs "Has" Approaches

Share this article
OOP vs Generics: "Is" vs "Has" Approaches

As Bjarne Stroustrup points out, "C++ is a multi-paradigm language." It supports many different programming styles, or paradigms, and object-oriented programming is only one of these. Some of the others are structured programming and generic programming.

As Thomas Becker explains in this interesting article, there’s a tension between generic programming and OOP. Here’s the opinion of Alexander Stepanov, an elder statesman of C++, on OOP, quoted in that article:

Let us start with a little trivia quiz. Who said the following things about object-oriented programming?

"I find OOP technically unsound."

"I find OOP philosophically unsound."

"I find OOP methodologically wrong."

"I have yet to see an interesting piece of code that comes from these OO people."

"I think that object orientedness is almost as much of a hoax as artificial intelligence."

All the quotes above are from an interview with Alexander Stepanov, the inventor of the STL and elder statesman of generic programming.

To have a concrete idea about the generics flexibility, let’s compare the implementation of a class calculating a tax in OOP and generic programming.

Let’s explore a major difference between the two approaches, which could explain Alexander Stepanov’s opinion about the OOP approach. To illustrate this, let’s take a basic tax calculator as an example.

generics1

CTaxCalculator collaborates only with classes derived from ICalculator. We have to inherit from ICalculator and override some virtual methods to implement our algorithm.

By contrast, here’s an example of the generic TaxCalculator:

generics2

The CGenericTaxCalculator class is not limited to working with a specific kind of class; it can work with any type capable of calculating the tax, regardless of that type’s class hierarchy.

The OOP approach is more of an “is-oriented approach”: inheritance is overused, and in almost all OOP code, each class A collaborates with another class B if B is a kind of another class, abstract or not.

On the other hand, with the generic approach, a class A collaborates with B if B has some specific methods and fields — no need to inherit from a specific class.

This makes generic programming more natural and flexible: it allows the developer to adopt a “has-oriented approach”. OOP is more rigid due to the high coupling generated by inheritance, which forces the developer to follow an “is-oriented approach”.

Think about it: the “has-oriented approach” is the more natural one. Indeed, in the real world I collaborate with a person who has specific skills, no matter whether they are from a specific family.

The flexibility of generic programming can make it a preferred choice for modern C++ design, as pointed out by Andrei Alexandrescu:

Modern C++ Design defines and systematically uses generic components - highly flexible design artifacts that are mixable and matchable to obtain rich behaviors with a small, orthogonal body of code.

Three points in his statement are particularly interesting:

  • Modern C++ Design defines and systematically uses generic components.
  • Highly flexible design.
  • Obtain rich behaviors with a small, orthogonal body of code.

To sum up, generic programming is more natural and flexible than the OOP approach, and it provides more options for writing efficient code.

Share this article