The diamond problem, or multiple inheritance, is handled by Scala using Traits, which are similar to Java interfaces. Traits are more flexible than interfaces and can include implemented methods. This makes traits similar to mixins in other languages.
Scala does not support inheritance from multiple classes, but a user can extend multiple traits in a single class:
trait traitA {
def name = println("This is the 'grandparent' trait.")
}
trait traitB extends traitA {
override def name = {
println("B is a child of A.")
super.name
}
}
trait traitC extends traitA {
override def name = {
println("C is a child of A.")
super.name
}
}
object grandChild extends traitB with traitC
grandChild.name
Here grandChild
is inheriting from both traitB
and traitC
, which in turn both inherit from traitA
. The output (below) also shows the order of precedence when resolving which method implementations are called first:
C is a child of A.
B is a child of A.
This is the 'grandparent' trait.
Note that, when super
is used to invoke methods in class
or trait
, linearization rule come into play to decide call hierarchy. Linearization order for grandChild
will be:
grandChild -> traitC -> traitB -> traitA -> AnyRef -> Any
Below is another example:
trait Printer {
def print(msg : String) = println (msg)
}
trait DelimitWithHyphen extends Printer {
override def print(msg : String) {
println("-------------")
super.print(msg)
}
}
trait DelimitWithStar extends Printer {
override def print(msg : String) {
println("*************")
super.print(msg)
}
}
class CustomPrinter extends Printer with DelimitWithHyphen with DelimitWithStar
object TestPrinter{
def main(args: Array[String]) {
new CustomPrinter().print("Hello World!")
}
}
This program prints:
*************
-------------
Hello World!
Linearization for CustomPrinter
will be:
CustomPrinter -> DelimitWithStar -> DelimitWithHyphen -> Printer -> AnyRef -> Any