In object-oriented programming (OOP), inheritance is a feature that allows a class or an interface to inherit attributes and behaviour from another class or interface. The class that is being inherited, is known as the parent class, while the class that inherits is termed as the child class.
In Java, inheritance can be implemented either through classes or interfaces. In the case of class, the parent class provides behavioural implementation (non-abstract method) that its child class acquires and reuses. But in the case of interfaces, the parent interface only supplies behavioural specification (abstract method) and the implementation is provided only when a class implements the interface.
Multiple Inheritance is a type of inheritance in which a class inherits more than one class. It may increase the complexity of a program as it can introduce deadly diamond or ambiguity problems. Apart from this, one also has to take care of special rules to prevent ambiguities, leading to extra efforts to deal with such cases.
Therefore, unlike C++, Java doesn’t support multiple inheritance of implementation. As a result, a class cannot have more than one superclass or parent class. However, it does support this type of inheritance in the case of the interface. A basic construct, named interface, consists only of declaration, not implementation. Hence, an interface can inherit multiple interfaces.
interface A { // members } interface B { // members } interface C extends A, B{ // members }
It is also known as the deadly diamond of death. This problem arises when a class acquires properties from multiple parent classes. For instance, suppose there are two classes, namely Person and Employee and both are having a common functionality getAge().
If a new class tries to inherit Programmer and Person at the same time, then it would automatically get getAge() method from both the parent classes. Further, the class would have two versions of getAge() with different implementations.
As a result, it would create ambiguity problem for the compiler, while identifying which version of getAge() to be selected – Person or Programmer.
This ambiguity or confusion is termed the diamond problem.
Therefore, Java doesn’t support multiple inheritance in classes.
As we know, multiple inheritance is not supported in the case of classes. It happens because two classes having the same method and different implementations can create ambiguity.
To check this on a programmatic level, we’ll be trying to implement the inheritance in form of a program.
Program:
class Employee { float salary; // getting age of an employee int getAge(){ return 21; } } class Person { String name; // getting age of a person int getAge(){ return 23; } } // Trying to apply multiple inheritance by extending two class at time class Programmer extends Employee,Person{ public static void main(String[] args) { Programmer programmer = new Programmer(); // Trying to get Age of a programmer System.out.println("Total salary for you programmer :: "+programmer.getAge()); } }
Error:
error: '{' expected class Programmer extends Employee,Person{ ^
Explanation:
Java doesn’t provide support for multiple inheritance of implementation ( non-abstract method or concrete class) but in the case of inheritance of interfaces or specifications (abstract methods), Java provides support for it.
It is because an interface can only provide only a declaration of a method, not implementation. As a result, when a class implements multiple interfaces and if a common method is available in those interfaces, it has to provide a single implementation which doesn’t create ambiguity.
An interface can have multiple parent interfaces at the same time. The functionality’s been demonstrated in the below example.
Program:
interface Employee { // getting age of an employee int getProgrammerAge(); } interface Person { // getting age of a person int getProgrammerAge(); } // Applying multiple inheritance by extending two interfaces at a time interface Programmer extends Employee,Person{ String getProgrammerName(); } class Program implements Programmer{ public static void main(String[] args) { Program code1 = new Program(); // Trying to get Age of a programmer System.out.println("The code is written by :: "+code1.getProgrammerName()+" and age :: "+code1.getProgrammerAge()); } @Override public int getProgrammerAge() { return 21; } // Overriding the method inherited from the interface @Override public String getProgrammerName() { return "Kui"; } }
Output:
The code is written by :: Kui and age :: 21
Explanation:
The default method that was introduced in Java 8, is the solution of the diamond problem or ambiguity problem. A default method is an implementation method within an interface. It is not mandatory for implementing classes to override it as its implementation is already provided by the interface.
It allows multiple inheritance to some extent. A default method with the same method name can be present in two or more interfaces. If a class implements them, then it would inherit properties of both.
In the case of default methods, Java defines a set of rules which needs to follow:
1) When a class overrides a default method of the implementing interface, then the class implementation would take the priority.
Example.
interface A { default void display() { System.out.println("I am a method from interface A"); } } interface B { default void display() { System.out.println("I am a method from interface B"); } } class C implements A,B{ @Override public void display() { System.out.println("I am a method from class C"); } public static void main(String[] args) { C obj = new C(); obj.display(); } }
Output:
I am a method from class C
2) When a class doesn’t provide implementation, then an error would occur.
Example:
interface A { default void display() { System.out.println("I am a method from interface A"); } } interface B { default void display() { System.out.println("I am a method from interface B"); } } class C implements A,B{ public static void main(String[] args) { C obj = new C(); obj.display(); } }
Error:
error: types A and B are incompatible; class C implements A,B{ ^ class C inherits unrelated defaults for display() from types A and B
3) If an interface is having a default method and is extended by another interface which consists same default method, then the most recent inheriting interface’s version in the hierarchy is considered.
Example.
interface A { default void display() { System.out.println("I am a method from interface A"); } } interface B extends A { default void display() { System.out.println("I am a method from interface B"); } } class C implements A,B{ public static void main(String[] args) { C obj = new C(); obj.display(); } }
Output:
I am a method from interface B
Java also allows the privilege to explicitly refer to a particular interface’s default implementation.
InterfaceName.super.methodName( )
This post was last modified on March 10, 2024