The Two Different Types of Inheritance

If, like me, you started life as a C++ developer, you will be surprised to learn that there are actually two completely different notions of Inheritance. In C++, these two different notions get squashed together, but they’re still there.

Imagine we are defining a base class to represent a financial security. In C++ it might look something like this:

class Security {
   public:
   virtual double GetPrice(double interestRate) = 0;
}

Any class that inherits from this base class has to implement the GetPrice method. Apart form that, they may have nothing else in common.

Now, suppose we are writing a base class that encapsulates our database access logic. Again, in C++, it might look a little like this:

class DatabaseAccessor {
   private:
   bool WriteToDatabase(string query) {
   // Implementation here
   }

   string ReadFromDatabase(string query) {
   // Implementation here
   }
}

These two examples illustrate the two different notions of inheritance, interface inheritance and implementation inheritance.

Interface inheritance, also known as type inheritance, is when we use inheritance to specify a common api across different classes. In our first example, every class that implements the Security class will have a public GetPrice method that takes a double argument and returns a double. There can be lots of different Security subclasses, that all calculate their price differently. But they all share the same interface for this functionality. This is interface inheritance.

Now, let’s look at our second example. Any class that inherits from DatabaseAccessor will have a shared implementation for reading from and writing to databases. We are using inheritance here to make our code easier to maintain and re-use. This is implementation inheritance.

When we write C++ we don’t normally distinguish between these two things. Indeed we can mix them freely. For example, suppose we had another class:

class RateCurve {
public:
   virtual double GetRateAt(time_t date);
   double Discount(double value, time_t date) {
      return value * GetRateAt(date);
   }
}

The method GetRateAt defines an interface as it’s a virtual function with no implementation. The method Discount comes with an implementation that will be shared between subclasses. So whenever we inherit from RateCure we will be using interface and implementation inheritance at the same time!

In a language like C# things are quite different. Interface and Implementation inheritance are handled explicitly and separately. If you would like to share implementation you inherit from a class. If you would like to use a common API you implement an interface. Interfaces are defined like so:

public interface ISecurity {
   public double GetPrice(double rate);
}

An interface cannot contain any fields, and (at least up to C# 8.0) interface methods cannot have implementations. This all means that it is a little bit easier to reason about our code. The disadvantage is that we cannot use both interface and implementation inheritance at the same time.

Leave a Reply

Your email address will not be published. Required fields are marked *