Home > Software design >  Concrete example for the definition of parallel inheritance
Concrete example for the definition of parallel inheritance

Time:10-09

While reading Dive Into Design Patterns by Alexander Shvets, I stumbled across the following statement in the section "Favor Composition Over Inheritance":

Trying to reuse code through inheritance can lead to creating parallel inheritance hierarchies

According to this site the definition of parallel inheritance is the situation in which subclassing a class requires creating yet another subclass elsewhere. I'm interested in knowing what would be this kind of scenario, where we'd have to subclass all over the place, and further more the why of it: why would we have to create the subclass elsewhere? Does the need arise from the context and the problem we are trying to solve, or is it induced by the structure of the (at least) two class hierarchies and composition between them? While here is an attempt to give a mathematical definition for the parallel inheritance, the need for the implication is not clear to me.

CodePudding user response:

I understand this like that. Imagine you have

public abstract class CarBase
{
    // all cars run on liquid fuel, right? This is 1955
    public decimal FuelVolume { get; set; }
}

Then you inherit this and create your PUTruck, SportsCar, Sedan etc

Suddenly, this is 2022 and you have Electric car. You will probably do

public abstract class ElectricCarBase : CarBase
{
    public decimal ChargeVolume { get; set; }
}

^^ this will come with all the nastiness of unused and unneeded properties, bunch of noise, like Antifreeze and fuel lines. And you endup in parallel inheritance. You will need to create all sort of adapters to support all this..

Enter "Composition Over Inheritance"

public abstract class CarBase
{
    public List<IFuelProvider> FuelSources { get; set; }
}

public interface IFuelProvider 
{
    
    public FuelType TypeOfFuel { get; set; }

    public string MeasureUnit { get; set; }

    public int FuelUnits { get; set; }
}

Now, you can support Gas, Electric or Hybrid

This is my understanding. Welcome to disagree

CodePudding user response:

When it comes to inheritance, it seems we can always take examples from the Animal Kingdom. So we have a class hierarchy of Animal like this.

interface Animal {
    void eat(Food someFood);
}

But every Animal has its own special Food. So when we subclass Animal with Dog we need to subclass Food with DogFood and when we subclass Animal with Cat we need to subclass Food with CatFood and so on.

Parallel hierarchies can occur naturally in a problem domain, in which case it may be sensible to model them the same way in code. But parallel hierarchies can also occur artificially in a solution domain, and that verbosity may be undesirable.

On StackOverflow, the syntactic question that often arises from this scenario is, how do I make sure my Animal doesn't eat the wrong Food?

  • Related