While doing some development with Scala I discovered that it is possible to match combinations of a class and traits. It might seem obvious if you already know it, but I didn’t.
What happened is that I needed something like matching that kind of combination… and this speaks to something about Scala that I love: it becomes intuitive after a while. So how did I find that such matching is possible? I simply tried… =)
This is what this feature looks like:
msg match { case x: X with Z => println("matching combination!") }
In this case, X would be a class, and Z a trait. The case x will be triggered only if msg is an instance of class X and mixes in trait Z. With this, we make sure to have access to all members both from the class and from the trait, while being really type safe about the matching. No unsupported combinations will pass through, and no need for castings, like would be necessary in Java.
Lets try a dummy example. Imagine we have a Superman class, and two traits: BlueCape and RedCape, like the following code:
class Superman(val realname: String) trait BlueCape trait RedCape
Now, we want to match on a Superman instance, but we want to know if it is fake or not. Finally, we also want to print the guy’s name, which means we need access to the realname field. This is how you could do that:
def whichSuperman(superman: AnyRef) = superman match { case s: Superman with RedCape => println("real superman: " + s.realname) case f: Superman with BlueCape => println("fake superman: " + f.realname) }
Flexible and type safe! And if the traits had any field, we would be able to access them as well. Quick sample test code:
val mys = new Superman("clark") with RedCape val myf = new Superman("clurk") with BlueCape whichSuperman(mys) whichSuperman(myf)
The part that matches the class is not very useful in this example, since this could be defined in the function parameter, but it was in my local scenario, where we are using actors and the messages can be AnyRef.
If you want to know a bit more about pattern matching, I wrote about it a while ago here. I also described how to match a range of numbers here.