Mark Thomas

Deceptively random thoughts

Scala: Traits and Self Types

with 5 comments

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.

What is a trait?

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.

Self Types

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]

Written by Mark Thomas

September 5th, 2008 at 9:48 pm

Posted in Feed to Planet TW,Scala,Software

Tagged with ,