Scala has a few features that, for those who come from a Java or C# background, provide new ways of modelling components and services. I’m going to write a few posts on this, but begin by describing some of the language features that enable them. First up is traits.
A trait is a collection of fields and methods. Traits can be mixed in to classes to add new features or to modify behaviour. Scala’s Ordered trait is a good example of this:
trait Ordered[A] {
def compare(that: A): Int
def < (that: A): Boolean = (this compare that) < 0
def > (that: A): Boolean = (this compare that) > 0
def <= (that: A): Boolean = (this compare that) <= 0
def >= (that: A): Boolean = (this compare that) >= 0
def compareTo(that: A): Int = compare(that)
}
By mixing-in Ordered to a new class, then you can get four useful operators by just implementing compare. This is quite powerful, for example:
class Money extends Ordered[Money] with SomeOtherTrait {
...
def compare(that: Money) = {
...
}
}
As classes can be composed of many traits, this creates a powerful way of building richer classes from simpler ones by layering in capabilities.
Ordered can be mixed in to any class; it doesn’t depend on any methods or fields of the class that it is mixed in to. Sometimes it’s useful for a trait to be able to use the fields or methods of a class it is mixed in to, this can be done by specifying a self type for the trait. A self type can be specified for a class or a trait as follows:
trait SpellChecker { self =>
...
}
self within the context of this trait will refer to this. Aliasing this is useful for nested classes or traits where it would otherwise be difficult to access a particular this. The syntax can be extended to specify a lower-bounds on this, when this is done the trait or class can use the features of this lower-bound class, so it can extend or modify its behaviour.
trait SpellChecker { self: RandomAccessSeq[char] =>
...
}
The compiler will check that any class in a hierarchy including SpellChecker is or extends RandomAccessSeq[char], so SpellChecker can now use the fields or methods of RandomAccessSeq[char]