One of the most powerful (and cool) features in Scala is that you can use traits as stackable modifications.
Let’s see how it works with a simple tutorial 🙂
Our goal is to create a list of ordered colours, let’s call it ColourMixer. First we create a class to represent what a basic (empty) colour mixer is:
class ColourMixer {
def colours: List[String] = List();
override def toString = colours mkString ", "
}
Let’s create our Legos blocks!
trait Red extends ColourMixer {
abstract override def colours = "red" :: super.colours
}
trait Green extends ColourMixer {
abstract override def colours = "green" :: super.colours
}
trait Blue extends ColourMixer {
abstract override def colours = "blue" :: super.colours
}
…wait a second! Are we abstracting a concrete method???
Traits are dynamically bound, while classes are statically bound: classes select a specific implementation according to the declared type, instead traits do it at runtime. Because of this property, we cannot say what implementation super is referring to — that’s why the abstract keyword is appropriate here. We will be able to decide only at runtime…and that’s why we can now play Legos!
val bgr = new ColourMixer with Red with Green with Blue println(s"BGR: $bgr") // it prints: "BGR: blue, green, red"; val rgb = new ColourMixer with Blue with Green with Red println(s"RGB: $rgb") // it prints: "RGB: red, green, blue"
Note that the application order is usually from the last to the first trait.
How cool is that! 😀