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! 😀