48

I want to do the following, but the self-type line just doesn't compile. Do I have this syntax wrong or is this just impossible?

trait A {
  def aValue = 1
}
trait B {
  def bValue = 1
}
trait C {
  a : A, b : B =>
  def total = a.aValue + b.bValue
}

class T extends C with A with B { ...
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Michael Lorton
  • 43,060
  • 26
  • 103
  • 144

2 Answers2

81

You can have a single self-type which is a compound type.

Try this:

trait A {
  def aValue = 1
}
trait B {
  def bValue = 1
}
trait C {
  self: A with B =>
  def total = aValue + bValue
}

class ABC extends A with B with C
4

With one trait you can do it with structural type:

trait C {
  self: { def aValue: Int
          def bValue: Int } =>

  def total = aValue + bValue
}

class ABC extends C {
  def aValue = 1
  def bValue = 1
}

Reflection used.

But, firstly you should not overuse self-types because of principle of least power.

Methods from question can be added simply by extending other tait:

trait C extends A with B{
  def total = aValue + bValue
}

or type both methods explicitly:

trait C {
  def aValue: Int
  def bValue: Int

  def total = aValue + bValue
}

Where to use self-types?

Self-types are usually used with classes. This is a good way for trait to require being a subclass of a desired class.

There is also one good use of self-type with triats: when you want to manipulate order of class initialization with multi-inheritance.

Waldemar Wosiński
  • 1,490
  • 17
  • 28