1. Introduction
Scala provides a developer with wide opportunities for designing data structures with traits. One of the most considerable features is the class composition with traits extension and mixins.
2. Enriching Classes with Traits
Consider the design of a simple class to represent some entity, such as a car. To present the general entity, we can use a trait:
trait Car {
def model: String
def horsePower: Int
}
Then, we may construct more specific entities:
class BMW(val model: String, val horsePower: Int) extends Car
In this way, an instance of the BMW class implements the fields of the Car trait:
val bmw = new BMW("F15", 309)
bmw.model // F15
bmw.horsePower // 309
Now, let’s imagine that we want to provide the option of also having a JSON view for Car instances. Scala gives us the tools for class enrichment via the traits mixin. This approach usually doesn’t require us to change the code of our class.
Once we’ve already extended a class from some trait, then we can mix it with another one. In this case, it’s enough to mix the relevant trait (say, Marshaller) into the class. This new trait extends the Car trait and can access its fields model and horsePower:
trait Marshaller extends Car {
def toJson: String = s"{${"\"model\""}:$model," +
s"\n${"\"horsePower\""}:$horsePower}"
}
Now, if we want an instance of our BMW class to be able to print JSON, we can use with keyword to mix in the Marshaller trait when we create it:
val bmwWithJson = new BMW("F15", 309) with Marshaller
And it’s possible to call the toJson method on the new instance:
val jsonView = bmwWithJson.toJson // {"model":F15,\n"horsePower":309}
3. Conclusion
This article gave an overview of class composition with traits in Scala. There are also a few other aspects of mixins, such as the use of self-types, the order of initialization, stackable modifications with traits, and cake-pattern, but we have already seen the power of traits composition for designing modular and composable data structures.
As usual, these examples are available over on GitHub.