Java Multiple Inheritance
Multiple Inheritance is a feature of an object-oriented concept, where a class can inherit properties of more than one parent class. The problem occurs when there exist methods with the same signature in both the superclasses and subclass. On calling the method, the compiler cannot determine which class method to be called and even on calling which class method gets the priority.
Note: Java doesn't support Multiple Inheritance
Example 1:
// Java Doesn't support Multiple Inheritance
import java.io.*;
// First Parent Class
class Parent1 {
void fun() { System.out.println("Parent1"); }
}
// Second Parent Class
class Parent2 {
void fun() { System.out.println("Parent2"); }
}
// Inheriting Properties of
// Parent1 and Parent2
class Test extends Parent1, Parent2
{
// main method
public static void main(String args[])
{
// Creating instance of Test
Test t = new Test();
t.fun();
}
}
Output: Compilation error is thrown
Conclusion: As depicted from code above, on calling the method fun() using Test object will cause complications such as whether to call Parent1’s fun() or Parent2’s fun() method.
Example 2: Java Diamond Problem Similar Scenario
GrandParent
/ \
/ \
Parent1 Parent2
\ /
\ /
Test
// Java Diamond Problem Similar Scenario
import java.io.*;
// GrandParent Class
class GrandParent {
void fun() {
System.out.println("Grandparent");
}
}
// Inheriting GrandParent
class Parent1 extends GrandParent {
void fun() {
System.out.println("Parent1");
}
}
// Inheriting GrandParent
class Parent2 extends GrandParent {
void fun() {
System.out.println("Parent2");
}
}
// Child Class inheriting Parent1 and Parent2
class Child extends Parent1, Parent2
{
// main method
public static void main(String args[])
{
Child t = new Child();
t.fun();
}
}
Output:
When you run the fun()
method in the Test
class, it throws a compiler error due to multiple inheritance, which causes the diamond problem (common in languages like C++). In this case, the code doesn't know whether to call Parent1
's or Parent2
's fun()
method, leading to ambiguity. To avoid such complications, Java does not support multiple inheritance with classes.
Java avoids multiple inheritance with classes because it can lead to complex issues, such as problems with casting, constructor chaining, and other operations. Moreover, multiple inheritance is rarely needed, so Java excludes it to maintain simplicity and clarity in code.
Using Default Methods and Interfaces for Multiple Inheritance
Java 8 supports default methods where interfaces can provide a default implementation of methods. And a class can implement two or more interfaces. In case both the implemented interfaces contain default methods with the same method signature, the implementing class should explicitly specify which default method is to be used in some method excluding the main() of implementing class using super keyword, or it should override the default method in the implementing class, or it should specify which default method is to be used in the default overridden method of the implementing class.
Example 1: Demonstrating Multiple Inheritance through default methods
// Interface 1
interface PI1 {
default void show(){
System.out.println("Default PI1");
}
}
// Interface 2
interface PI2 {
default void show(){
System.out.println("Default PI2");
}
}
class TestClass implements PI1, PI2 {
// Overriding default show method
@Override
public void show(){
PI1.super.show();
PI2.super.show();
}
// Declared new Method
public void showOfPI1() {
PI1.super.show();
}
// Declared new Method
public void showOfPI2() {
PI2.super.show();
}
// main Method
public static void main(String args[]) {
// Instance of Class
TestClass d = new TestClass();
// Using show Method
d.show();
// Executing the Methods
System.out.println("Now Executing showOfPI1()" +
" showOfPI2()");
d.showOfPI1();
d.showOfPI2();
}
}
Output
Default PI1 Default PI2 Now Executing showOfPI1() showOfPI2() Default PI1 Default PI2
Note: If we remove the implementation of default method from "TestClass", we get a compiler error. If there is a diamond through interfaces, then there is no issue if none of the middle interfaces provide implementation of root interface. If they provide implementation, then implementation can be accessed as above using super keyword.
Example 2:
// Java program to demonstrate How Diamond Problem
// Is Handled in case of Default Methods
// Interface 1
interface GPI {
// Default method
default void show()
{
// Print statement
System.out.println("Default GPI");
}
}
// Interface 2
// Extending the above interface
interface PI1 extends GPI {
}
// Interface 3
// Extending the above interface
interface PI2 extends GPI {
}
// Main class
// Implementation class code
class TestClass implements PI1, PI2 {
// Main driver method
public static void main(String args[])
{
// Creating object of this class
// in main() method
TestClass d = new TestClass();
// Now calling the function defined in interface 1
// from whom Interface 2and 3 are deriving
d.show();
}
}
Output
Default GPI