tags:

views:

73

answers:

1

Given two independent traits:

trait T1 {
    def x = 42
}

trait T2 {
    def x = 0
}

If I try to define a class mixing in these two traits like:

class C extends T1 with T2

I get a compiler error:

error: overriding method x in trait T1 of type => Int;
method x in trait T2 of type => Int needs `override' modifier
class C extends T1 with T2
      ^
one error found

Now suppose T1 and T2 have been developed independently, hence no override as they do not override anything. How can C be defined then? Like this:

class C extends T1 with T2 {
    override def x = super.x
}

?

+9  A: 

This is known as the diamond problem. In Scala there are two ways to solve this:

trait T1 {
  def x = 0
}

trait T2 {
  def x = 42
}

class C extends T1 with T2 {
  override def x = super.x
}

class D extends T2 with T1 {
  override def x = super.x
}

If you call new C().x now, you will get 42 because Scala uses the implementation of the trait you mixed in last. new D().x will yield 0 by the way. This means, that in order to solve the diamond problem, you have to define explicitly which implementation you would like to use.

The other way is as follows:

trait T {
  def x: Int
}

trait T1 extends T {
  override def x = 0
}

trait T2 extends T {
  override def x = 42
}

class C extends T1 with T2

A call to new C().x will still yield 42 because T2 is the last trait mixed in. The difference is that you don't have to define x in C.

Michel Krämer
This is interesting. If the two definitions of `x` in `T1` and `T2` have different types, it seems to be an unavoidable problem.Is there a clever way in Scala to fix these name conflicts if the types don't match?
Mike
Use my first example and then define `C` as follows: `class C extends T1 with T2 { override def x = super[T1].x }`. Of course, you may also call `super[T2].x`.
Michel Krämer