Inheritance of Interface in Java with Examples - GeeksforGeeks

10 Jun, 2020
Inheritance is an important pillar of OOPs(Object Oriented Programming). It is the mechanism in java by which one class is allowed to inherit the features(fields and methods) of another class. Like a class, an interface can have methods and variables, but the methods declared in an interface are by default abstract (only method signature, no body).
In this article, we will understand how the concept of inheritance is used in the interface.
An interface is a set of specifications or statements that define what a class can do without specifying how the class will do it. The interface is always abstract. A concrete class must implement all the abstract methods specified in the interface. Java does not support the concept of multiple inheritances to avoid the diamond problem encountered in C++ without using a virtual base class. However, Java supports multiple interface inheritance where an interface extends more than one super interfaces. The following is the syntax used to extend multiple interfaces in Java:
access_specifier interface subinterfaceName extends superinterface1, superinterface2, ...... {
// Body}
The following is an example which implements the multiple inheritances in interfaces:
Java
// Java program to demonstrate// the multiple inheritance// in interface  // Interface to implement the// addition and subtraction methodsinterface Add_Sub {    public void add(double x, double y);    public void subtract(double x, double y);}  // Interface to implement the// multiplication and divisioninterface Mul_Div {    public void multiply(double x, double y);    public void divide(double x, double y);}  // Calculator interface which extends// both the above defined interfacesinterface Calculator extends Add_Sub, Mul_Div {    public void printResult(double result);}  // Calculator class which// implements the above// interfacepublic class MyCalculator implements Calculator {      // Implementing the addition    // method    public void add(double x, double y)    {        double result = x + y;        printResult(result);    }      // Implementing the subtraction    // method    public void subtract(double x, double y)    {        double result = x - y;        printResult(result);    }      // Implementing the multiplication    // method    public void multiply(double x, double y)    {        double result = x * y;        printResult(result);    }      // Implementing the division    // method    public void divide(double x, double y)    {        double result = x / y;        printResult(result);    }      // Implementing a method    // to print the result    public void printResult(double result)    {        System.out.println(            "The result is : " + result);    }      // Driver code    public static void main(String args[])    {          // Creating the object of        // the calculator        MyCalculator c = new MyCalculator();        c.add(5, 10);        c.subtract(35, 15);        c.multiply(6, 9);        c.divide(45, 6);    }}
The result is : 15.0
The result is : 20.0
The result is : 54.0
The result is : 7.5

Superinterface-Subinterface relationship: A subinterface type reference variable can be assigned to super interface type reference variable. Let us consider an example where we have an interface named animal which is extended by an interface mammal. We have a class named horse which implements the animal interface and the class named human which implements mammal. When we assign the mammal to an animal, it compiles without any error because a mammal is also an animal. That is:
// Animal Interfacepublic interface Animal {    // body}  // Mammal interface which extends// the Animal interfacepublic interface Mammal extends Animal {    // body}  // Horse which implements the// Animalclass Horse implements Animal {    // body}  // Human which implements the// mammalclass Human implements Mammal {    // body}  public class GFG {    public static void main(String args[])    {        Animal a = new Horse();        Mammal m = new Human();          // This compiles without any error        // because mammal is also an animal,        // subtype reference variable m        // is assigned to the super type        // reference variable  a        a = m;    }}
How does multiple inheritance affect the variables:
There are two possible cases while inheriting the variables defined in one interface into others. They are:
Case 1: A subinterface inherits all the constant variables of the super interface. If a subinterface declares a constant variable with the same name as the inherited constants, then the new constant variable hides the inherited one irrespective of the type. For example:JavaJava// Java program to demonstrate the// inheritance of the variables  // Defining an interface X// with some variablesinterface X {    int VALUE = 100;    int h = 10;}  // Defining the interface Y// with the same variables// as the interface Xinterface Y extends X {    int VALUE = 200;    String h = "Hello World";    int sub = VALUE - X.VALUE;}  // A class which implements the// above interfacepublic class GFG implements Y {      // Printing the values of the    // variables    public static void main(String args[])    {        System.out.println("X.VALUE = " + X.VALUE);        System.out.println("Y.VALUE = " + Y.VALUE);        System.out.println("sub = " + sub);        System.out.println("X.h = " + X.h);        System.out.println("h = " + h);    }}Output:X.VALUE = 100
Y.VALUE = 200
sub = 100
X.h = 10
h = Hello World

Java
// Java program to demonstrate the// inheritance of the variables  // Defining an interface X// with some variablesinterface X {    int VALUE = 100;    int h = 10;}  // Defining the interface Y// with the same variables// as the interface Xinterface Y extends X {    int VALUE = 200;    String h = "Hello World";    int sub = VALUE - X.VALUE;}  // A class which implements the// above interfacepublic class GFG implements Y {      // Printing the values of the    // variables    public static void main(String args[])    {        System.out.println("X.VALUE = " + X.VALUE);        System.out.println("Y.VALUE = " + Y.VALUE);        System.out.println("sub = " + sub);        System.out.println("X.h = " + X.h);        System.out.println("h = " + h);    }}
X.VALUE = 100
Y.VALUE = 200
sub = 100
X.h = 10
h = Hello World

Case 2: When a subinterface extends the interfaces having the constant variables with the same name, Java gives a compilation error because the compiler cannot decide which constant variable to inherit. For example:JavaJava// Java program to demonstrate the// case when the constant variable// with the same name is defined  // Implementing an interface// X with a variable Ainterface X {    int A = 10;}  // Implementing an interface// Y with the same variableinterface Y {    String A = "hi";}  // Implementing an interface which// extends both the above interfacesinterface Z extends X, Y {    // body}  // Creating a class which implements// the above interfacepublic class GFG implements Z {    public static void main(String args[])    {          // Shows compile time error if        // the backslash is removed        // System.out.println(Z.A);        System.out.println(X.A);        System.out.println(Y.A);    }}Output:10
hi

Java
// Java program to demonstrate the// case when the constant variable// with the same name is defined  // Implementing an interface// X with a variable Ainterface X {    int A = 10;}  // Implementing an interface// Y with the same variableinterface Y {    String A = "hi";}  // Implementing an interface which// extends both the above interfacesinterface Z extends X, Y {    // body}  // Creating a class which implements// the above interfacepublic class GFG implements Z {    public static void main(String args[])    {          // Shows compile time error if        // the backslash is removed        // System.out.println(Z.A);        System.out.println(X.A);        System.out.println(Y.A);    }}
10
hi

How do multiple inheritances affect the methods and ways to handle the conflicts:
All the abstract and default methods of a super interface are inherited by the subinterface. When a subinterface extends more than one interface, then either a default-default conflict or an abstract-default conflict arises. These conflicts are handled by either of the following rules:
Override the conflicting method with an abstract method.Override the conflicting method with a default method and provide a new implementation.Override the conflicting method with a default method and call the default method of the immediate super interface.
Override the conflicting method with an abstract method.
Override the conflicting method with a default method and provide a new implementation.
Override the conflicting method with a default method and call the default method of the immediate super interface.
Default-default Conflict: The default-default conflict arises when two interfaces implement the same default methods with different operations and the compiler doesn’t know which task needs to be performed when both these interfaces are extended by a third interface. For example:
// Interface oneinterface one {  // A default methoddefault void    print()    {        System.out.println("one");    }}  // Interface twointerface two {  // Another default method// with the same namedefault void    print()    {        System.out.println("two");    }}
We can apply the above-discussed rules to solve the above conflict. The following are the ways to handle the conflict:
Rule 1: Override the conflicting method with an abstract method. For example:interface four extends one, two {      // Implementing another method    void print();}Rule 2: Override the conflicting method with a default method and provide a new implementation. For example:interface four extends one, two {  // Declare another method and// provide an implementationdefault void    print()    {        System.out.println("four");    }}Rule 3: Override the conflicting method with a default method and call the default method of the immediate super interface. For example:interface four extends one, two {  // Override the method with a// default method and give the// signature of what to performdefault void    print()    {        two.super.print();        System.out.println("-four");    }}
Rule 1: Override the conflicting method with an abstract method. For example:interface four extends one, two {      // Implementing another method    void print();}
interface four extends one, two {      // Implementing another method    void print();}
Rule 2: Override the conflicting method with a default method and provide a new implementation. For example:interface four extends one, two {  // Declare another method and// provide an implementationdefault void    print()    {        System.out.println("four");    }}
interface four extends one, two {  // Declare another method and// provide an implementationdefault void    print()    {        System.out.println("four");    }}
Rule 3: Override the conflicting method with a default method and call the default method of the immediate super interface. For example:interface four extends one, two {  // Override the method with a// default method and give the// signature of what to performdefault void    print()    {        two.super.print();        System.out.println("-four");    }}
interface four extends one, two {  // Override the method with a// default method and give the// signature of what to performdefault void    print()    {        two.super.print();        System.out.println("-four");    }}
Abstract-default Conflict: The abstract-default conflict arises when one interface implements the default method and another interface defines an abstract method with the same name. While implementing both the interfaces, then we need to provide an implementation of the method but default methods don’t need an implementation. Even in this case, the compiler doesn’t know which method to execute. For example:
// Implementing the interface// one with a default methodinterface one {default void    print()    {        System.out.println("one");    }}  // Implementing another interface// with an abstract method of the// same nameinterface three {    void print();}
We can apply the above-discussed rules to solve the above conflict. The following are the ways to handle the conflict:
Rule 1: Override the conflicting method with an abstract method. For example:interface five extends one, three {    void print();}}Rule 2: Override the conflicting method with a default method and provide a new implementation. For example:interface five extends one, three {default void    print()    {        System.out.println("five");    }}Rule 3: Override the conflicting method with a default method and call the default method of the immediate super interface. For example:interface five extends one, three {default void    print()    {        one.super.print();        System.out.println("-four");    }}
Rule 1: Override the conflicting method with an abstract method. For example:interface five extends one, three {    void print();}}
interface five extends one, three {    void print();}}
Rule 2: Override the conflicting method with a default method and provide a new implementation. For example:interface five extends one, three {default void    print()    {        System.out.println("five");    }}
interface five extends one, three {default void    print()    {        System.out.println("five");    }}
Rule 3: Override the conflicting method with a default method and call the default method of the immediate super interface. For example:interface five extends one, three {default void    print()    {        one.super.print();        System.out.println("-four");    }}
interface five extends one, three {default void    print()    {        one.super.print();        System.out.println("-four");    }}
Overriding inherited static methods in interface inheritance:
In the interface inheritance, the static methods are not changed throughout the execution and they are not inherited. Hence, they cannot be overridden. However, if a class implements multiple interfaces without having a parent-child relationship by providing the methods with the same signature and the class does not override those methods, then a conflict occurs. For example:
// Interface A with an// abstract methodinterface A {    void m();}  // Interface B which doesn't// implement the above interface// and have the same abstract methodinterface B {    void m()    {        System.out.println("In B");    }}  // An Abstract class with the// normal method Mclass abstract C {    public void m()    {        System.out.println("In C");    }}public class test extends C    implements A, B {      public static void main(String args[])    {        // Creating an object of test        test t = new test();          // Here, a conflict occurs as to        // which method needs to be called        t.m();    }}
To overcome this problem there are three rules:
Rule 1: Superclass has higher precedence than interfaces. This means that the superclass method is called.Rule 2: Derived interfaces have higher precedence than the super interfaces in the inheritance hierarchy. If I1 has a method m1() and I2 extends I1 and overrides m1() then I2 is the most specific version and has higher precedence.Rule 3: The class must override the method as needed. For example:public class test extends C    implements A, B {      // Overriding the conflicting    // method    public void m()    {        System.out.println("test");    }    public static void main(String args[])    {        test t = new test();        t.m();    }}
Rule 1: Superclass has higher precedence than interfaces. This means that the superclass method is called.
Rule 2: Derived interfaces have higher precedence than the super interfaces in the inheritance hierarchy. If I1 has a method m1() and I2 extends I1 and overrides m1() then I2 is the most specific version and has higher precedence.
Rule 3: The class must override the method as needed. For example:public class test extends C    implements A, B {      // Overriding the conflicting    // method    public void m()    {        System.out.println("test");    }    public static void main(String args[])    {        test t = new test();        t.m();    }}
public class test extends C    implements A, B {      // Overriding the conflicting    // method    public void m()    {        System.out.println("test");    }    public static void main(String args[])    {        test t = new test();        t.m();    }}
To conclude, though interfaces support multiple inheritances, there are few limitations and conflicts which needs to be handled.
Abstract Class and Interface
java-inheritance
java-interfaces
Java Programs
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Iterate Over the Characters of a String in Java
How to Get Elements By Index from HashSet in Java?
Java Program to Write into a File
Java Program to Read a File to String
How to Write Data into Excel Sheet using Java?
Java Servlet and JDBC Example | Insert data in MySQL
Removing last element from ArrayList in Java
How to Replace a Element in Java ArrayList?
Java Program to Find Sum of Array Elements
Tic-Tac-Toe Game in Java