Multiple Inheritance

Why Java doesn't support it

Interview Relevant: Diamond problem explanation
5 min read

Multiple Inheritance in Java

Java does NOT support multiple class inheritance to avoid the Diamond Problem. However, it supports multiple interface implementation.

The Diamond Problem

When a class inherits from two classes that have a common ancestor with the same method, ambiguity arises about which version to use.

āš ļø Diamond Problem: If A has method m(), B and C both extend A and override m(), and D extends both B and C - which m() does D inherit?

āœ“ Java's Solution: Single class inheritance + multiple interface implementation. Default methods in interfaces handle conflicts explicitly.

Code Examples

The Diamond Problem explained

java
1// Diamond Problem Illustration (Why Java avoids it)
2
3//       Animal (eat method)
4//        /    \
5//    Bird      Mammal
6//   (fly)     (walk)
7//        \    /
8//         Bat   ← Which eat() to inherit? Ambiguous!
9
10// In C++ (allows multiple inheritance):
11// class Animal { void eat(); }
12// class Bird extends Animal { void fly(); }
13// class Mammal extends Animal { void walk(); }
14// class Bat extends Bird, Mammal { }  // PROBLEM!
15
16// āœ— NOT allowed in Java:
17// class Bat extends Bird, Mammal { }  // Compile Error!
18
19// āœ“ Java's approach - use interfaces
20interface Animal {
21    void eat();
22}
23
24interface Flyable extends Animal {
25    void fly();
26}
27
28interface Walkable extends Animal {
29    void walk();
30}
31
32class Bat implements Flyable, Walkable {
33    @Override
34    public void eat() {
35        System.out.println("Bat eating insects");  // One implementation
36    }
37    
38    @Override
39    public void fly() {
40        System.out.println("Bat flying at night");
41    }
42    
43    @Override
44    public void walk() {
45        System.out.println("Bat crawling");
46    }
47}

Resolving interface default method conflicts

java
1// Interface Default Method Conflicts (Java 8+)
2interface Interface1 {
3    default void show() {
4        System.out.println("Interface1 show");
5    }
6}
7
8interface Interface2 {
9    default void show() {
10        System.out.println("Interface2 show");
11    }
12}
13
14// Class must resolve the conflict explicitly
15class MyClass implements Interface1, Interface2 {
16    @Override
17    public void show() {
18        // Option 1: Provide own implementation
19        System.out.println("MyClass show");
20        
21        // Option 2: Choose one interface's version
22        // Interface1.super.show();
23        
24        // Option 3: Call both
25        // Interface1.super.show();
26        // Interface2.super.show();
27    }
28}
29
30// Without override - compile error:
31// class BadClass implements Interface1, Interface2 { }  // ERROR!

Multiple interfaces for multiple behaviors

java
1// Practical Multiple Inheritance via Interfaces
2interface Printable {
3    void print();
4    
5    default void printHeader() {
6        System.out.println("=== Document ===");
7    }
8}
9
10interface Saveable {
11    void save();
12    
13    default void autoSave() {
14        System.out.println("Auto-saving...");
15        save();
16    }
17}
18
19interface Exportable {
20    void export(String format);
21}
22
23// Document has multiple behaviors
24class Document implements Printable, Saveable, Exportable {
25    private String content;
26    
27    @Override
28    public void print() {
29        printHeader();  // Uses default method
30        System.out.println(content);
31    }
32    
33    @Override
34    public void save() {
35        System.out.println("Saving document...");
36    }
37    
38    @Override
39    public void export(String format) {
40        System.out.println("Exporting as " + format);
41    }
42}
43
44Document doc = new Document();
45doc.print();       // Printable
46doc.autoSave();    // Saveable (uses default method)
47doc.export("PDF"); // Exportable

Composition as an alternative

java
1// Composition over Inheritance - Often Better!
2// Instead of trying to inherit from multiple classes,
3// compose objects that provide the needed functionality
4
5class Engine {
6    public void start() {
7        System.out.println("Engine starting");
8    }
9}
10
11class Wheels {
12    public void roll() {
13        System.out.println("Wheels rolling");
14    }
15}
16
17class GPS {
18    public void navigate() {
19        System.out.println("GPS navigating");
20    }
21}
22
23// Car HAS-A Engine, Wheels, GPS (composition)
24// Instead of trying to inherit all three
25class Car {
26    private Engine engine = new Engine();
27    private Wheels wheels = new Wheels();
28    private GPS gps = new GPS();
29    
30    public void start() {
31        engine.start();
32    }
33    
34    public void drive() {
35        wheels.roll();
36        gps.navigate();
37    }
38}
39
40// Benefits:
41// - More flexible than inheritance
42// - Can change components at runtime
43// - No diamond problem
44// - Loose coupling

Use Cases

  • Understanding Java design decisions
  • Interface-based design
  • Default method conflict resolution
  • Composition over inheritance
  • Plugin/extension architectures
  • Mixin-like patterns with interfaces

Common Mistakes to Avoid

  • Trying to extend multiple classes
  • Not resolving default method conflicts
  • Overcomplicating with too many interfaces
  • Using inheritance when composition is better
  • Misunderstanding interface inheritance
  • Ignoring diamond problem in design