Scala abstract types in classes within objects

柔情痞子 提交于 2019-12-02 08:54:33
ghik

This is a problem with path dependent types.

The test method of object h does not expect, as you would assume, a subtype of Parent.Inner. It expects a subtype of h.Self which is a slightly different type. Even though Child.Inner is a subtype of Parent.Inner, it is not a subtype of h.Self and that's why the compiler complains.

The problem with type members is that they are path dependent - they're bound to their enclosing instance and scalac will not allow you to pass type member of one instance where type member of another instance is expected. Child.Inner is not bound to any instance at all and will also be rejected.

Why is this needed? Look at this very similar code:

object Main {
  class C extends Child.Inner { type Self = C }

  val h: Parent.Inner = new C
  h.test[Child.Inner]
}

When looking at types, this code is exactly the same as yours (in particular, the type of h is exactly the same). But this code is clearly incorrect, because h.Self is actually C and Child.Inner is not a subtype of C. That's why scalac correctly rejects it.

You would expect that in your snippet scalac should remember that the type of h is exactly Parent.Inner, but unfortunately it doesn't keep that information. It only knows that h is some subtype of Parent.Inner.

It appears that you are thinking of def inner = new Inner() as a field instead of thinking of it as a val. The difference is that a value is determined at the time a class is loaded, while the value using the def keyword is determined at run-time. This may not be exactly what you are looking for, as it answers another question, but there seems to be something funky going on here.

Since I am curious myself:

val p : Parent.Inner = Child.inner

This is obviously true, with this line:

class Inner extends Parent.Inner

however if we do:

val h = Parent.inner h.test[Parent.Inner]

does not work either with the following error:

type arguments [Parent.Inner] do not conform to method test's type parameter bounds [T <: h.Self] h.test[Parent.Inner]

even more curiously (or maybe not curiously, since this is a subtype of everything) this works: h.test[Nothing]

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