Reputation: 4053
Let's have this simplified code:
class Base {
self =>
type Actual <: Base {type Actual = self.Actual}
def me: Actual = this.asInstanceOf[Actual]
}
class A extends Base {
override type Actual = A
}
class B extends A {
override type Actual = B
}
println((new B).me)
I want the me
to always have a proper return type (for fluent interface). Unfortunately this code is crashing with:
test.scala:13: error: overriding type Actual in class A, which equals this.A;
type Actual has incompatible type
override type Actual = B
^
one error found
How to implemented the desired behavior and why is it crashing on a second type member override?
Upvotes: 1
Views: 70
Reputation: 4239
@flavian's answer is right. For reasons why such multiple overriding doesn't work, check this discussion https://groups.google.com/forum/#!topic/scala-user/si51jb9RS68
Particularly, this point:
To override a class member, the type of the overriding has to "subsume" the type of the overridden member. (Spec section 5.1.4)
For type aliases, "subsume" means they have to be equivalent. (Spec section 3.5.2, toward the end.)
So, you are able to write this, because type A
is obviously equivalent ot A
:
class B extends A {
override type Actual = A
}
But types A
and B
aren't equivalent, that's why you can't override type A
with type B
.
Upvotes: 1
Reputation: 28511
This is usually achieved through f bounded polymorphism.
class Base[Actual <: Base[Actual]] {
def me: Actual
}
class A extends Base[A]
class B extends Base[A]
If you would like B
to extend A
you need A
to pass through a type param again:
class A[Actual <: Base[Actual]] extends Base[Actual]
Upvotes: 1