Multiple Inheritance with Interfaces

First things first. What is multiple inheritance means ?

When one class can inherit characteristics and features from multiple classes, it's called as multiple inheritance. As an example,

class FuelVehicle{
   public void fillFuel(){  
   }
}
 
class ElectricVehicle{
   public void charge(){  
   }
}

class HybridCar extends ElectricVehicle,FuelVehicle{  
}

HybridCar class inherits from both FuelVehicle and ElectricVehicle classes. Then HybridCar class get the ability of using the features of both the mother classes. In simple words, an object of the HybridCar class can call both the methods, fillFuel() and charge(). Up to now, all is well.

But, there can be a problem in a scenario like the following.

class Vehicle{
   public void start(){
   }
 }
 
class FuelVehicle extends Vehicle{
   public void start(){
      //Overridden
   }

   public void fillFuel(){  
   }
}
 
class ElectricVehicle extends Vehicle{
   public void start(){
      //Overridden
   }

   public void charge(){  
   }
}

 class HybridCar extends ElectricVehicle,FuelVehicle{  
 }
 
 public static void main(String[] args){
    HybridCar hybridCar = new HybridCar();
    hybridCar.start();
 }

Now the FuelVehicle class and ElectricVehicle classes also are inherited from a class call Vehicle. The Vehicle mother class consists a method call start, and that method is overridden in both FuelVehicle & ElectricVehicle classes with different implementations. Because the mechanism a electric vehicle starts & a fuel vehicle starts are different from one to another.
Then as the HybridCar class inherits from both ElectricVehicle & FuelVehicle, it gets this start() method into it. But that method is implemented differently in his parent classes. So who's implementation he should follow? A problem of ambiguity is raised.
And this problem is called as The Diamond Problem.

With languages like C++, when at the time object oriented was introduced multiple inheritance existed in the language, facilitating the capability of following the above scenario. But when it came to languages like Java, C#, multiple inheritance was not allowed in those languages to avoid the ambiguity that could occur due to the diamond problem.

But still, there was this requirement of the ability to give multiple behaviors to the same class to produce a better code with object oriented concepts. When you can't inherit from multiple classes, how to achieve such agenda? This is the place where interfaces comes to play. You can't inherit from from only one class, but you can implement many interfaces.

If you don't know what is an interface is, in simple words it's an agreement or a contract that the class get bounded to after implementing that interface to the class. In the sense, if you implement a certain interface to a class, that class MUST implement the empty body methods defined in that interface, inside that class. It's the agreement.

Let's present the same example above with interfaces.

public interface Vehicle{
   public void start();
}
 
public interface FuelPowered extends Vehicle{
   public void start();
   public void fillFuel();
}
 
public interface ElectricPowered{
   public void start();
   public void charge();
}

public class HybridCar implements FuelPowered,ElectricPowered{ 
   public void start(){
   }

   public void fillFuel(){
   } 

   public void charge(){
   }
}
 
 public static void main(String[] args){
    HybridCar hybridCar = new HybridCar();
    hybridCar.start();
 }

Here what I have done is instead of using a class hierarchy, I've replaced them with interfaces.
Vehicle interface has the start(), but not implemented. (There are better ways of designing than using a interface called Vehicle. But I don't want to go into them as I want to keep this example simple as possible and to prove the focused point.)
By inheriting from Vehicle interface, both FuelPowered & ElectricPowered interfaces get the start() method, but as those also are interfaces, the method is implemented there. Plus those interfaces have their own methods like fillFuel() & charge() too.
Now comes the real business, the HybridCar class. The real business happens where, there is awareness about it. By implementing the  two interfaces FuelPowered & ElectricPowered, the behaviors of a fuel powered car and an electric powered car is given to the hybrid car. So HybridCar class in a contract to implement the methods related to both of those behaviors.
So when you crate an object of the HybridCar class, and call the method start(), the implementation you've done inside that class will be called, without an ambiguity problem which was the case earlier. And by that, it means we've solved the diamond problem successfully.

Further Learning: Did you know this is possible ?

When Vehicle was a parent class in the hierarchy, and when HybridCar was it's grand child, um sure you would agree that the following is possible,

public static void main(String[] args){
   Vehicle vehicle = new HybridCar();
   vehicle.start();
 }

We can store object of the child classes in the references of the parent classes. That's a very rule of inheritance. And at run-time the dynamic binding will happen and the features related to the object type will be stored in the reference variable. If we want to call methods specific to the object type, we can downcast the reference type anytime and do so. These are things we all know.

But did you know, that the same thing is possible with interfaces too. Just give a look for the code beneath.

public static void main(String[] args){
   Vehicle vehicle = new HybridCar();
   vehicle.start();
   ((FuelPowered)vehicle).fillFuel();
   ((ElectricPowered)vehicle).charge();
 
   FuelPowered fuelPowered  = new HybridCar();
   fuelPowered.fillFuel();
 
   ElectricPowered electricPowered = new HybridCar();
   electricPowered.charge();
}

When Vehical, FuelPowered, ElectricPowered all are interfaces, what's shown above is possible too.
Implementing an interface bounds the class to a contract or an agreement. But that's not all it does.
After implementing an interface to a class, you get the ability of storing the objects of that class in the reference variables of that implemented interface. According to that you can store objects of HybridCar in any reference types of either Vehicle, FuelPowered or ElectricPowered. That's another privilege you get with implementing interfaces.

Hope you learnt something here.
Cheers :)

Comments

Popular posts from this blog

WPF Dispatcher - Accessing UI Thread From Another Thread

Downgrade NuGet Packages - Visual Studio

Callbacks With Interfaces Or Delegates