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"); // ExportableComposition 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 couplingUse 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