The diamond problem
Multiple inheritance suffers from the diamond problem.
Let's have a look at the following diagram:
Here, both B and C extend A, and then D extends B and C. Some ambiguities might arise from this. Let's say that there was a method that was originally defined in A, but both B and C override it. What would happen if D calls this method? Which one will it exactly call?
All the preceding questions make things ambiguous and this could lead to mistakes. Let's try and reproduce this in Scala using traits:
trait A {
def hello(): String = "Hello from A"
}
trait B extends A {
override def hello(): String = "Hello from B"
}
trait C extends A {
override def hello(): String = "Hello from C"
}
trait D extends B with C {
}
object Diamond extends D {
def main(args: Array[String]): Unit = {
System.out.println(hello())
}
}
What would be the output of the program? Here is the output:
Hello from C
What if we just change the D trait to look as follows:
trait D extends C with B {
}
Then the output of our program will be as follows:
Hello from B
As you can see, even though the example is still ambiguous and prone to errors, we can actually tell exactly which method will be called. This is achieved using linearization, which we will look at in greater depth in the next section.