Scala: illegal inheritance; self-type Y does not conform to X's selftype SELF

流过昼夜 提交于 2019-12-18 19:00:49

问题


I have a trait, which takes a type parameter, and I want to say that the objects that implements this trait will also conform to this type parameter (using generics, for Java's compatibility)

The following code:

trait HandleOwner[SELF <: HandleOwner[SELF]] {
self : SELF =>
    // ...
    def handle: Handle[SELF]
}

trait Common[SELF <: Common[SELF]]  extends HandleOwner[SELF] {
    // ...
}

Gives me the following error:

illegal inheritance;  self-type test.Common[SELF] does not conform to
test.HandleOwner[SELF]'s selftype SELF

If I change Common to:

trait Common[SELF <: Common[SELF]]  extends HandleOwner[SELF] {
self : SELF =>
    // ...
}

Then the error goes away.

Why is it that I have to repeat the same declaration in every non-concrete type. If I would have a base class, and say "extends Comparable", I don't have to repeat "extends Comparable" in every derived type, as long as the concrete classes implement the compareTo method. I think it should be the same thing here. I am just saying that a type extending HandleOwner will be also a SELF, and the compiler should just accept it, and take it into consideration while not requiring every non-concrete subtype to repeat the same thing again.

A am doing this to avoid having to use a class-cast, but I will be literally extending every class from this trait, and I don't see that I should have to repeat this declarations hundreds or even thousands of times!


回答1:


Self type is more akin to generic constraint than to inheritance. With class C[A <: B], the constraint must be repeated all along in subclasses : class D[A <: B] extends C[A]. The constraint must be repeated until it is satisfied, that is until you have chosen an actual parameter type which indeed satisfies <: B. Same for the self type. Writing self: A => does not makes your type extend A. It ensures that it will ultimately have to be mixed in with A before it is actually instantiated.

On the opposite, when you extend Comparable, you have made your class a Comparable, not put a constraint for later on. But the fact that you need to implement compareTo has still to be repeated all along with abstract until you actually implement it.

Certainly the compiler could do without repeating <: B, self: A =>, and abstract, the info is available to it. This is language designer choice. At least, having to repeat self: A => is not different from the rules everywhere else.



来源:https://stackoverflow.com/questions/7378901/scala-illegal-inheritance-self-type-y-does-not-conform-to-xs-selftype-self

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!