Tour of Scala

Class Composition with Mixins

Mixins are traits which are used to compose a class.

In [1]:
abstract class A {
  val message: String
class B extends A {
  val message = "I'm an instance of class B"
trait C extends A {
  def loudMessage = message.toUpperCase()
class D extends B with C

val d = new D
println(d.message)  // I'm an instance of class B
println(d.loudMessage)  // I'M AN INSTANCE OF CLASS B
I'm an instance of class B
defined class A
defined class B
defined trait C
defined class D
d: D = [email protected]

Class D has a superclass B and a mixin C. Classes can only have one superclass but many mixins (using the keywords extends and with respectively). The mixins and the superclass may have the same supertype.

Now let's look at a more interesting example starting with an abstract class:

In [2]:
abstract class AbsIterator {
  type T
  def hasNext: Boolean
  def next(): T
defined class AbsIterator

The class has an abstract type T and the standard iterator methods.

Next, we'll implement a concrete class (all abstract members T, hasNext, and next have implementations):

In [3]:
class StringIterator(s: String) extends AbsIterator {
  type T = Char
  private var i = 0
  def hasNext = i < s.length
  def next() = {
    val ch = s charAt i
    i += 1
defined class StringIterator

StringIterator takes a String and can be used to iterate over the String (e.g. to see if a String contains a certain character).

Now let's create a trait which also extends AbsIterator.

In [4]:
trait RichIterator extends AbsIterator {
  def foreach(f: T => Unit): Unit = while (hasNext) f(next())
defined trait RichIterator

This trait implements foreach by continually calling the provided function f: T => Unit on the next element (next()) as long as there are further elements (while (hasNext)). Because RichIterator is a trait, it doesn't need to implement the abstract members of AbsIterator.

We would like to combine the functionality of StringIterator and RichIterator into a single class.

In [5]:
object StringIteratorTest extends App {
  class RichStringIter extends StringIterator("Scala") with RichIterator
  val richStringIter = new RichStringIter
  richStringIter foreach println
defined object StringIteratorTest

The new class RichStringIter has StringIterator as a superclass and RichIterator as a mixin.

With single inheritance we would not be able to achieve this level of flexibility.



Tour of Scala