Multiple Inheritance in Scala

Teepika R M
5 min readAug 10, 2020

In this post, lets see about multiple inheritance in Scala. We will start with what’s multiple inheritance, the diamond problem caused due to it and how the diamond problem is resolved using traits in Scala.

Multiple Inheritance:

Having sub classes that inherits from two or more parent classes is known as multiple inheritance.

Multiple inheritance is not supported in Scala. But to understand what problem it causes, imagine multiple inheritance is supported in Scala. The following illustration is a piece of code that demonstrates one,

abstract class A{
def func1(param1:String):String
}
class B extends A{
def func1(param1:String)=param1+" concatenated string"
}
class C extends A{
def func1(param1:String)=param1.toUpperCase();
}
class D extends B with C{ // Causes error, since you cannot inherit from two parent classes
}
val D_obj= new D
D_obj.func1("hellow")

Here we have an abstract class A and two classes B and C, both extends A and have different implementations for abstract function func1. Class D is the child class that inherits from two parent classes B and C (multiple inheritance).

The diamond problem caused due to multiple inheritance:

Invoking func1 from the child class D confuses the compiler to use which implementation? func1 from B or func1 from C? This problem is known the diamond problem.

Diamond problem is the reason why multiple inheritance is not supported in many of the programming languages like Scala,Java,C# etc.

Now lets see, how multiple inheritance is kind of achieved in Scala through traits. In Scala you cannot inherit multiple base classes but you can inherit multiple traits. But the same question pops out here also, implementation reference how the problem is resolved? The answer is through linearization of classes and traits that are mixed into a class.

When you have multiple traits inherited, during instantiation(object creation) Scala forms the linear order of classes and traits inherited as per the linearization rule.

For eg consider the linear order formed as per the linearization rule be,

C->A->D->B->E->AnyRef->Any // Read the order from the left to right. left most is the deepest sub class

Imagine super keyword is used to invoke the common function(different implementations in Class B and Class E) in the class D. Scala refers the linear order and invokes the implementation defined in the class B.

How the linear order is formed by Scala? Based on the linearization rule.

Linearization Rule:

1) Start at the first extended class or trait and write that complete hierarchy down. We will call this the linearized hierarchy

2) Take the next trait and write this hierarchy down

  • Now remove all classes/traits from this hierarchy which are already in the linearized hierarchy
  • Add the remaining traits to the bottom of the linearized hierarchy to create the new linearized hierarchy

3) Repeat step 2 for every trait.

It can easily be understood with an example.

Example code:
class A {
def foo() = "A"
}
trait B extends A {
override def foo() = "B" + super.foo()
}
trait C extends B {
override def foo() = "C" + super.foo()
}
trait D extends A {
override def foo() = "D" + super.foo()
}
object LinearizationPlayground {
def main(args: Array[String]) {
var d = new A with D with C with B;
println(d.foo) // CBDA????
}
}

The linear order of the above program is, CBDA

Lets break down and see how the above linear order is been formed:

1) Start at the first extended class or trait and write that complete hierarchy down. We will call this the linearized hierarchy.

var d = new A with D with C with B // And trait D extends A

The first extended class is D. Write its complete hierarchy down.

D->A->AnyRef->Any. Call this the linearized hierarchy.

D->A->AnyRef->Any // linearized hierarchy

2) Take the next trait and write this hierarchy down

var d = new A with D with C with B // And trait C extends B and trait B extends A

The next trait is C and write its hierarchy, C->B->A->AnyRef->Any

  • Now remove all classes/traits from this hierarchy which are already in the linearized hierarchy

D->A->AnyRef->Any // linearized hierarchy

C->B->A->AnyRef->Any //Remove all the classes/traits which already in linearized hierarchy.

  • Add the remaining traits to the bottom of the linearized hierarchy to create the new linearized hierarchy

C->B->D->A->AnyRef->Any

3) Repeat step 2 for every trait.

Repeat:

2) Take the next trait and write this hierarchy down

var d = new A with D with C with B // And trait B extends A

The next trait is B and write its hierarchy, B->A->AnyRef->Any

  • Now remove all classes/traits from this hierarchy which are already in the linearized hierarchy
  • Add the remaining traits to the bottom of the linearized hierarchy to create the new linearized hierarchy

Nothing left to add to the linearized hierarchy.

Step 3 is over since all the inherited classes/traits are processed.

Finally the linearization order is C->B->D->A

That’s why when foo is invoked, it first starts from trait C and goes on appending strings until it reaches the super base class A.

Hope this blog helps you understand multiple inheritance,diamond problem, how the problem is resolved through traits in Scala following linearization.

--

--

Teepika R M
Teepika R M

Written by Teepika R M

AWS Certified Big Data Specialty| Linux Certified Kubernetes Application Developer| Hortonworks Certified Spark Developer|Hortonworks Certified Hadoop Developer

No responses yet