Diamond problem in Java

Harjot Singh
3 min readNov 30, 2023

--

The “diamond problem” is a term used in the context of object-oriented programming, particularly in languages that support multiple inheritance. It refers to a specific issue that arises when a class inherits from two classes that have a common ancestor. The problem gets its name because, in a class diagram, the inheritance structure looks like a diamond shape.

Let’s consider an example in Java to illustrate the diamond problem:

class Animal {
void makeSound() {
System.out.println("Generic animal sound");
}
}interface Swimmer {
void swim();
}
interface Flyer {
void fly();
}
class Fish extends Animal implements Swimmer {
@Override
void makeSound() {
System.out.println("Bubble bubble");
}
@Override
public void swim() {
System.out.println("Swimming like a fish");
}
}
class Bird extends Animal implements Flyer {
@Override
void makeSound() {
System.out.println("Chirp chirp");
}
@Override
public void fly() {
System.out.println("Flying like a bird");
}
}
// Diamond problem occurs here
class Duck extends Fish implements Flyer {
// Uncommenting this method will result in a compilation error
/*
@Override
void makeSound() {
System.out.println("Quack quack");
}
*/
// Uncommenting this method will resolve the compilation error, but behavior may not be as expected
/*
@Override
public void swim() {
System.out.println("Swimming like a duck");
}
*/
}
public class Main {
public static void main(String[] args) {
Duck duck = new Duck();
duck.makeSound(); // Ambiguity in method resolution
duck.swim(); // Ambiguity in method resolution
duck.fly(); // Resolves fine
}
}

In the example above, the Duck class inherits from both Fish and Flyer. Both Fish and Bird classes inherit from the common ancestor Animal. The issue arises because Duck inherits the makeSound() method from both Fish and Bird, leading to ambiguity in method resolution. Uncommenting either of the conflicting methods in Duck would result in a compilation error.

To avoid the diamond problem, some programming languages, like Java, support single inheritance and allow multiple inheritance through interfaces, which don’t contain implementations. This helps in avoiding the conflict that arises from inheriting the same method from multiple paths in the inheritance hierarchy.

So does it mean that we can’t do multiple inheritance in Java?

No! we can but there is another way to do that via Interference

In Java, multiple inheritance can be achieved through interfaces, as Java supports interface-based multiple inheritance. While classes in Java can only extend one class, a class can implement multiple interfaces. This allows a class to inherit behavior from multiple sources.

Here’s an example demonstrating how to achieve multiple inheritance through interfaces:

// Interface for swimming behavior
interface Swimmer {
void swim();
}
// Interface for flying behavior
interface Flyer {
void fly();
}
// Class representing an animal
class Animal {
void makeSound() {
System.out.println("Generic animal sound");
}
}
// Class representing a fish, implementing the Swimmer interface
class Fish extends Animal implements Swimmer {
@Override
void makeSound() {
System.out.println("Bubble bubble");
}
@Override
public void swim() {
System.out.println("Swimming like a fish");
}
}
// Class representing a bird, implementing the Flyer interface
class Bird extends Animal implements Flyer {
@Override
void makeSound() {
System.out.println("Chirp chirp");
}
@Override
public void fly() {
System.out.println("Flying like a bird");
}
}
// Class representing a duck, implementing both Swimmer and Flyer interfaces
class Duck extends Animal implements Swimmer, Flyer {
@Override
void makeSound() {
System.out.println("Quack quack");
}
@Override
public void swim() {
System.out.println("Swimming like a duck");
}
@Override
public void fly() {
System.out.println("Flying like a duck");
}
}
public class Main {
public static void main(String[] args) {
Duck duck = new Duck();
duck.makeSound();
duck.swim();
duck.fly();
}
}

In this example, Fish and Bird represent specific behaviors (swimming and flying, respectively) through interfaces Swimmer and Flyer. The Duck class then implements both interfaces, effectively inheriting behaviors from both Swimmer and Flyer. This way, you can achieve the benefits of multiple inheritance while avoiding the issues associated with the diamond problem.

--

--

Harjot Singh
Harjot Singh

Written by Harjot Singh

Just an ordinary guy who like to code | SDE by Profession and Passion | Full stack Developer | Open to collab, for freelance work just a DM away 😄

No responses yet