Reputation: 4007
Consider this:
object TypeProblem {
trait A {
type T
val set = Set[T]()
}
trait B {
def b()
}
trait FooBad { this: A =>
type T <: B
def x {
set.foreach(_.b())
}
}
trait FooOk { this: A =>
type MyT <: B
type T = MyT
def x {
set.foreach(_.b())
}
}
}
The compiler complains that value b is not a member of FooBad.this.T So why does FooOk work where I define a new type MyT and assigning T to MyT?
Upvotes: 3
Views: 128
Reputation: 5712
The self type of FooBad
is expanded by the compiler to FooBad with A
(so that you can still access the members you define yourself). That means that T
gets the definition in A
, and not the one in FooBad
, as you'd expect. You can fix your code by changing the definition of FooBad
to explicitly add your own type:
trait FooBad { this: A with FooBad =>
..
}
or even better by using subclassing
trait FooBad extends A {
..
}
It is my belief that in most cases self-types should be replaced by plain subclassing. It is simpler to understand, less scary, and leads to better encapsulation.
Upvotes: 4