Summary
In the latest installment of his article series dedicated to Scala, Daniel Spiewak explains Scala's trait construct.
Advertisement
While Scala shares many similarities with Java, and Scala code is for the most part very readable to a Java developer, Scala also introduces constructs that do not have Java equivalents. Traits are one such example, explains Daniel Spiewak in the latest installment of his article series on Scala, Scala for Java Refugees Part 5: Traits and Types:
Scala doesn’t have any direct analogue to Java’s interfaces. This answer may seem a bit surprising, given what I’ve been saying about similarity to Java. The fact is that Java’s interfaces are really a very weak mechanism and a paltry imitation of their forebearer: multiple inheritance...
Java’s designers recognized the need for multiple typing... but they wanted to avoid the issues associated with inheriting conflicting method definitions along multiple paths. Their solution was to design the interface mechanism, a feature which allows multiple typing without the complications of multiple inheritance...
Scala recognizes that interfaces have their issues. So rather than blinding creating a reimplementation of the same problems found in either Java or C++, Scala takes a new approach. Inspired by a combination of Java’s interfaces and Ruby’s mixins, the designers of Scala have created the trait construct:
In the article, Spiewak explains that traits can contain both abstract members, as well as full method definitions. And a Scala class can also inherit from multiple traits in a way that carries type information to the inheriting class:
[Traits] allow inheriting classes to inherit from more than one trait. They pass on their type information and implementations to their children, as well as enforcing the abstract members. At first glance, this seems like it would be just as bad as straight-up multiple inheritance, but it turns out the problems have been mitigated in some very clever ways...
The real key to the power of traits is the way in which the compiler treats them in an inheriting class. Traits are actually mixins, not true parent classes. Any non-abstract trait members are actually included in the inheriting class, as in physically part of the class. Well, not physically, but you get the picture. It’s as if the compiler performs a cut-and-paste with the non-abstract members and inserts them into the inheriting class. This means that there’s no ambiguity in the inheritance path...
1. The traits in Scala are more like mixins, in that order of application is important - in my proposal you must explicitly resolve ambiguities, not rely on order of application to resolve ambiguity
2. In my suggestion methods could be added to a trait (or interface, which I am turning into a trait) without having to recompile classes that implement the trait, provided that a method body is given. For example you could add sort to List and it doesn't break old code, you don't even need to recompile a class that implements List.