In this blog we will discuss about a Trait and how Traits can help you to beautify your code by Multiple Inheritance.
Traits
Traits are a fundamental unit of code reuse in Scala. Trait encapsulates method and field definitions, which can be reused by mixing into classes.
Two most important concept about Traits are :-
- Widening from thin interface to rich interface
- Defining stackable modifications.
trait Philosophical {
def philosphize() {
println("I consume memory,therefore I am !")
}
}
Trait can be mixed with a class using either extends or with keyword.
class Frog extends Philosophical {
override def toString = "green"
}
As we know that Frog is a class which is a child class of AnyRef but it extends a Trait which also extends a class AnyRef so we can say that Frog will have a parent class or Trait as Philosophical which will extend the class AnyRef. Frog will not have a direct connection to AnyRef, it will first extends Philosophical which will further extends AnyRef.
Extending Traits
A trait can be extended by other traits, concrete class, abstract class and case class as well.
Traits extending a Traits
trait Animal {
def foo() {
println("This is a type of Animal")
}
}
trait Dog extends Animal {
override def toString = "Dog"
}
Abstract classes can extend a trait
abstract class Frog extends Animal {}
In this case, if we have some methods or fields declared in that trait, abstract class need to override it.
Classes extends a trait
class Frog extends Philosophical {
override def toString = "green"
}
Thin interface V/S Rich interface
One major use of traits is to automatically add methods to a class in terms
of methods. That is, traits can enrich a thin interface making it into a rich interface.
Rich interface
In case of rich interface we may have the implementation of methods and it depends on the need of a user whether the user wants to use the definition of the methods or user can override it according to the need.
Thin interface
In case of thin interface every class which extend that class need to override those methods, in case of thin interface we will not have the definition of those methods or fields and every time we need to override those methods to provide the definition.
Suppose more than one class extends the same trait so in case of thin interface we may need to override that same method and every time need to give the definition of that method, which can be reduced by the help of rich interface, we just need to override those methods whose definition we want to change.
Stackable modification
As we know class/trait can extend more than one trait at a time and if all of those trait have same method and we need to override that method then how we will get to know that which overridden method will be invoked. In such a situation how can we resolve that thing?
Trait plays an important role here. Stackable modifications state that “super” is accessed dynamically based on how the trait is mixed in, whereas in general super is statically determined.
import scala.collection.mutable.ArrayBuffer
trait WithLegs {
def legs: String = "Base"
}
trait TwoLegged extends WithLegs {
override def legs: String = "Two -> " + super.legs
}
trait FourLegged extends WithLegs {
override def legs: String = "Four -> " + super.legs
}
trait SixLegged extends TwoLegged {
override def legs: String = "Six -> " + super.legs
}
class ClassB extends FourLegged with TwoLegged {
override def legs = "B -> " + super.legs
}
res1: String = B -> Two -> Four -> Base
Lineraziation
Trait linearization is a process which comes in picture when ever we mix any number of traits and classes in a single trait.
Scala linearization is a process in which all traits are present in linear hierarchy, by this we can solve the diamond problem . Remember that the syntax to mixin traits is as follows: class A extends B with C with D
.
The rules for this process are as follows:
- Start from the very first class or trait which is extended and write the linearized hierarchy.
- Take the next trait and write this hierarchy down
- now remove all those classes and traits which we have already used in our previous linearized hierarchy.
- add the remaining traits to the bottom of the linearized hierarchy to create the new linearized hierarchy.
- repeat step 2 for every trait.
- Place the class itself as the last type extending the linearized hierarchy.
class Beast extends TwoLegged with FourLegged {
override def legs = super.legs
}
Without the Linearization process it would be unclear where the super.legs
resolves to because of the linearization process, the compiler determines that super
points to FourLegged
.
Let’s write this down by applying the rules mentioned above:
- Start at the first Start at the first extended class or trait and write that complete hierarchy down. The first trait is TwoLegged, so this leads to:
TwoLegged -> AnyRef -> Any - Take the next trait and write this hierarchy down. The next trait is FourLegged and the hierarchy is:
FourLegged -> AnyRef -> Any- now remove all classes/traits from this hierarchy which are already in the linearized hierarchy. This removes AnyRef and Any, so we are left with:
FourLegged - add the remaining traits to the bottom of the linearized hierarchy to create the new linearized hierarchy
FourLegged -> TwoLegged -> AnyRef -> Any
- now remove all classes/traits from this hierarchy which are already in the linearized hierarchy. This removes AnyRef and Any, so we are left with:
- repeat step 2 for every trait. There are no more traits, so we are done.
- Place the class itself as the last type extending the linearized hierarchy
Beast -> FourLegged -> TwoLegged -> AnyRef -> Any
The graphical representation looks like the picture below:

This hierarchy clearly shows that calling super from Beast will resolve to the FourLegged trait and thus the value of legs will be 4.
Hope this block will help you.
Happy Blogging!

1 thought on “Traits – The beauty of Scala5 min read”
Comments are closed.