monnef
monnef

Reputation: 4053

Multiple overriding of a type member

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

Answers (2)

Evgeny Veretennikov
Evgeny Veretennikov

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

flavian
flavian

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

Related Questions