Saturday, 4 January 2014

Scala traits

I mentioned in a recent post how some .Net developers are embracing F# as a more modern language than C#. This prompted me to check some of its features and in the end this took me take a glimpse to a couple of F# vs Scalar discussion. As I I lack of a "functional programming mindset" many elements in those discussions are alien to me, but the thing is that Scala sports a really interesting feature, traits/mixins.

Well, Traits/Mixins seem like an eternal source of conflict: what's the difference, are they just the same? I wrote about it some time ago and I think the conclusion I had drawn at that time after reading several materials on the topic is still right. Anyway, in Scala they're 2 parts of the same thing, we define traits, and then adding a trait to a class or instance is called mixin class composition. There are excellent examples like this all over the net, so I won't repeat code here. The idea is that traits can have both methods and properties (data fields), and can be mixed in into new classes or new instances, enabling some taste of Multiple Inheritance.

If we compare this to what is offered by Java 8 and Default Interface Implementation we can see that Scala traits are much more powerful. The Java 8 counterpart only allows inheriting behaviour (methods), while Scala allows inheriting both behaviour and state (notice that given than Scala Traits can have state, they have constructors. Furthermore, we can mixin traits not just into a new class, but directly into a new instance (I guess the compiler will do some magic under the covers to create new classes for such instances).

One thing that to my knowledge is missing is the ability to add a trait to an already existing instance (so we can't expand existing objects as we do in JavaScript, Groovy (ExpandoMetaClass) or even C# (with dynamic)).

So Scala traits are a really powerful feature that I would very much welcome in C#, but I've read some statements that confuse me a bit. Some people talk about how you can use traits for AOP. At first instance this article seemed really interesting. You use a trait to override a method to which you want to add the crosscutting concern. But after a second thought, the thing is that this leads to tons of code repetition. For each method you want to override you'll have to add one method to the trait with the extra code and the call to super, and you'll have to do this for each class. So, maybe it's that I'm missing something, but otherwise this approach seems terribly weak when compared to the normal AOP techniques using Dynamic Proxies and interception.

A concept sometimes mentioned when talking about Mixins and Traits is Monkey Patching. I think the difference lies on the fact that while Mixins/Traits are used when creating new classes (or instances), Monkey Patching is applied to existing classes or instances. In Scala I think you have access to some sort of Monkey Patching by means of implicit.

Finally, I'd like to recommend this excellent series comparing features in 3 of the more valued alternative JVM languages: Groovy, Scala and Clojure. By the way, I absolutely agree with this phrase by Martin Fowler mentioned there:

The legacy of Java will be the platform, not the language.

No comments:

Post a Comment