Scala Linearization is a deterministic process which comes into play when an object of a class is created which is defined using inheritance of different traits and classes. linearization helps to resolve the diamond problem which occurs when a class or trait inherits a same property from 2 different concrete classes or traits.
Syntax :
trait C{}
trait B{}
class A{}
object a_obj= new class A extends B with C
The linearization will look like as follows :-
C-> AnyRef-> Any
B-> AnyRef-> Any
A-> AnyRef-> Any
a_obj-> A-> C-> B-> AnyRef-> Any
Here Any is the superclass of all classes, also called the top class. It defines certain universal methods such as equals, hashCode, and toString. AnyRef represents reference classes. All non-value types are defined as reference types. AnyRef corresponds to java.lang.object . Every Scala trait and class implicitly extend these Scala objects at the end of linearization hierarchy.
Examples :
trait A
{
def name : String
}
trait B extends A
{
override def name : String = "class b"
}
trait C extends A
{
override def name : String = "class c"
}
class D extends B with C
{
override def name : String = super .name
}
object GFG
{
def main(args : Array[String])
{
var class _ d = new D
println(class _ d.name)
}
}
|
Output :
class c
Linearization for class D follows dark bold arrow. Inheritance for class D follows light arrow.

Trait linearization and inheritance diagram
As we can see in above diagram linearization will not be as same as inherited structure. Scala traits/classes are dynamically placed in linear order in which will the linearization will be applied as below.
D-> C-> B-> A-> AnyRef-> Any
Following rules are followed for the determining the linearization:
- Take the first extended trait/class and write its complete inherited hierarchy in vertical form, store this hierarchy as X.
- Take the next trait/class after the with clause, write its complete hierarchy and cancel the classes or traits that are repeated in hierarchy X. Add the remaining traits/classes to the front of the hierarchy X.
- Go to step 2 and repeat the process, until no trait/class is left out.
- Place the class itself in front of hierarchy as head for which the hierarchy is being written.
Let’s understand some examples.
Example :
class old _ Car
{
def method : String = "old car "
}
trait new _ Car _ Designs extends old _ Car
{
override def method : String = "Designing-> " + super .method
}
trait new _ Car _ Part extends old _ Car
{
override def method : String = "Add new part-> " + super .method
}
trait new _ Car _ Paint extends old _ Car
{
override def method : String = "Repainting-> " + super .method
}
class new _ Car extends new _ Car _ Paint with
new _ Car _ Part with new _ Car _ Designs
{
override def method : String = "new car-> " + super .method
}
object geekforgeeks
{
def main(args : Array[String])
{
var car 1 = new new _ Car
println(car 1 .method)
}
}
|
Output :
new car-> Designing-> Add new part-> Repainting-> old car
Example :
class flavour
{
def make (flavour : String) : Unit =
{
println(flavour)
}
}
trait texture extends flavour
{
abstract override def make (flavour : String)
{
super .make(flavour + "texture " )
}
}
trait cream extends texture
{
abstract override def make (flavour : String)
{
super .make(flavour + "with cream " )
}
}
trait jelly extends texture
{
abstract override def make (flavour : String)
{
super .make(flavour + "with jelly " )
}
}
trait cone extends flavour
{
abstract override def make (flavour : String)
{
super .make(flavour + "in cone " )
}
}
class Myflavour extends flavour with jelly
{
override def make (flavour : String)
{
super .make(flavour)
}
}
class Myflavour 2 extends flavour with cream with cone
{
override def make (flavour : String)
{
super .make(flavour)
}
}
object GFG
{
def main(args : Array[String])
{
var icecream 1 = new Myflavour
var icecream 2 = new Myflavour 2 with jelly
println(icecream 1 .make( "chocolate " ))
println(icecream 2 .make( "vanilla " ))
}
}
|
Output :
chocolate with jelly texture
()
vanilla with jelly in cone with cream texture
()
Important Points About Linearization
- Scala solves ambiguity of traits/classes by linearization process.
- Scala uses linearization whenever a new class has been instantiated. Taking all the traits/classes and forming a linear order which points to corresponding super classes/traits thus super method knows its parent method.
- These super method calling is done in a stackable manner.
- Linearization may or not be the same as the inherited mixins as they are written.
- We cannot explicitly add a class to inheritance when it is already been implicitly inherited in a linearization otherwise it will result in error as inheritance twice.
- No trait/class is ever repeated in linearization.