Multiple Inheritance
Why Java doesn't support it
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
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
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
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
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