Multiple Inheritance in Java

Multiple inheritance is a feature of some object-oriented computer programming languages in which an object or class can inherit characteristics and behavior from more than one parent object or parent class.

Till Java 1.7, Java did not support multiple inheritance. Since Java 8, we can realize the concept of multiple inheritance through the use of default methods without getting into the diamond problem.

1. What is Multiple Inheritance?

In multiple inheritance, a child class can inherit the behavior from more than one parent classes. Note that a Java class can implement multiple interfaces, but an interface does not define concrete behavior rather, interfaces are used for defining the contracts only. So implementing multiple interfaces does not add the behavior to a class, so it is not multiple inheritance.

In the following diagram, class D extends classes A and B. In this way, D can inherit the non-private members of both classes. But, in Java, we cannot use extends keyword with two classes. So this kind of multiple inheritance is not possible in Java.

Multiple inheritance
Multiple Inheritance

2. What are Default Methods?

If you have been in java programming for enough long time, you may realize how painful it can be to add a new method to an existing interface. We must implement that new method in all classes that implement the interface. It’s a really difficult job and often breaks the code and design. Well, Java 8 brought default methods to help solve this exact problem.

Default methods enable us to add new functionality to the interfaces and ensure backward compatibility for existing classes which implement that interface.

As their name implies, default methods in interfaces are methods that will be invoked by default – if not overridden in implementing classes. Let us understand with an example.

Moveable interface is an existing interface, and we want to add a new method moveFast(). If we add moveFast() method using the old technique, then all classes implementing Moveable will also be changed. So, let’s add moveFast() method as the default method.

public interface Moveable {

    default void moveFast() {
        System.out.println("I am moving fast");
    }
}

In this case, all the classes implementing Moveable interface do not need to change themselves (until some class specifically wants to override moveFast() method to add custom logic). All classes can directly call instance.moveFast() method.

class Animal implements Moveable { }

Animal tiger = new Animal();

//Call default method using instance reference
tiger.moveFast();

We can add as many default methods in an interface as we want.

3. How is Multiple Inheritance achieved with Default Methods?

Since Java 8, the interfaces not only define the contracts but also contain the behavior using the default methods. So, if a class implements two interfaces and both define default methods, then the class essentially inherits behaviors from two parents which is multiple inheritance.

For example, in below code Animal class does not define any of its own behavior; rather, it inherits behavior from parent interfaces.

interface Moveable {

    default void moveFast() {
        System.out.println("I am moving fast");
    }
}

interface Crawlable {

    default void crawl(){
        System.out.println("I am crawling");
    }
}

public class Animal implements Moveable, Crawlable { }

We can verify the behavior as follows:

Animal self = new Animal();

self.moveFast();
self.crawl();

4. Possible Conflicts

In the above example, we have two different interfaces and two different methods – so there is no conflict. What if both interfaces decide to define a new method with the same name? Well, they can define without a problem. But which method will be invoked when Animal instance will call the method by name.

interface Moveable {

    default void run() {
        System.out.println("I am moving fast");
    }
}

interface Crawlable {

    default void run(){
        System.out.println("I am crawling");
    }
}

public class Animal implements Moveable, Crawlable { }

Now what will happen when we call the animal.run() method?

Animal animal = new Animal();

animal.run();

That’s a conflicting situation. To solve the above conflict, the caller class must decide which run() method it wants to invoke and then call using the interface’s reference.

Moveable.super.run();   //Call Moveable's run() method

//or 

Crawlable.super.run();  //Call Crawlable's run() method

That’s all you should know about the multiple inheritance feature in Java 8, using default methods.

Happy Learning !!

Leave a Comment

  1. Even this code (note how I took the calls out of the static method by adding a Test class) still fails to pass the IDE’s error checking and you get an error on the Animal class with something like:

    Duplicate default methods named run with the parameters () and () are inherited from the types Crawlable and Moveable

    package com.foo.bar;
    
    
    	
    	interface Moveable
    	{
    	    default void run(){
    	        System.out.println("I am running, kid !!");
    	    }
    	}
    	  
    	interface Crawlable
    	{
    	    default void run(){
    	        System.out.println("I am running, daddy !!");
    	    }
    	}
    	
    	public class Animal implements Moveable, Crawlable 
    	{
    	    public void move() {
    	    	Moveable.super.run();
    	        Crawlable.super.run();
    	    }
    	}
    	  
    	public class Test 
    	{
    	    public static void main(String[] args) 
    	    {	
    	    	Animal animal = new Animal();
    	    	animal.move();
    	        //What will happen when below statement will execute
    	        //self.run();
    	    }
    	}
    
    Reply
      • Maybe I misunderstand, but class.super.method() does not solve the problem in my example above. I still get errors and I’m not in a static context…

        It’s a cool idea and I’d like to understand. To help me, please post some code that will not generate errors either in the IDE or at compile time? Thanks!

        Reply
        • interface Moveable
          {
              default void run(){
                  System.out.println("I am running, kid !!");
              }
          }
            
          interface Crawlable
          {
              default void run(){
                  System.out.println("I am running, daddy !!");
              }
          }
            
          public class Animal implements Moveable, Crawlable 
          {
              public static void main(String[] args) 
              {
                  Animal self = new Animal();
                  self.run();
              }
              
              public void run()
              {
              	Moveable.super.run();
          		Crawlable.super.run();
          	}
          }
          
          Reply
          • Many thanks! I see my error now – not having a method named “run()” to match the interface.

            The error message generated by that mistake was not helpful. It referenced “duplicate default methods” when in fact, the problem was the lack of a run() method in my Animal class…

            Great example – thanks for posting!

  2. This sounded great until I tried to put it into an IDE. Unless I made a mistake, the following code will not compile but will instead produce the error: “Cannot use super in a static context”

    package com.foo.bar;
    
    	interface Moveable
    	{
    	    default void run(){
    	        System.out.println("I am running, kid !!");
    	    }
    	}
    	  
    	interface Crawlable
    	{
    	    default void run(){
    	        System.out.println("I am running, daddy !!");
    	    }
    	}
    	  
    	public class Animal implements Moveable, Crawlable 
    	{
    	    public static void main(String[] args) 
    	    {
    	        Animal self = new Animal();
    	        Moveable.super.run();
    	        Crawlable.super.run();
    	    }
    	}
    

    Please let me know if I got it wrong…

    Reply
    • You are right. My point is to use Moveable.super.run() style method calls to avoid conflict. You can definitely use it outside static methods. Or you can test by removing static keyword from main mathod.

      Reply

Leave a Comment

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.