Why is upcasting necessary in this Scala code?

懵懂的女人 提交于 2019-12-05 16:35:56

问题


This compiles:

import scala.collection._

trait Foo[A, +This <: SortedSet[A] with SortedSetLike[A,This]]
extends SortedSetLike[A, This] { this: This =>

  def bar: This = (this: SortedSetLike[A,This]).empty

}

But if the upcast is removed it fails to compile:

import scala.collection._

trait Foo[A, +This <: SortedSet[A] with SortedSetLike[A,This]]
extends SortedSetLike[A, This] { this: This =>

  def bar: This = this.empty

}

Why? From the extends clause we know that Foo is a SortedSetLike[A, This], so the upcast is valid of course - but doesn't this show that the compiler has allowed conflicting inheritance to occur?


回答1:


The SortedSetLike trait inherits the empty method from SetLike.

/** The empty set of the same type as this set
* @return  an empty set of type `This`.
*/
def empty: This

But SortedSet overrides the empty method and has an explicit return type:

/** Needs to be overridden in subclasses. */
override def empty: SortedSet[A] = SortedSet.empty[A]

Since you specify that This is a subclass of SortedSet the compiler will find SortedSet's implementation of empty first, which returns a SortedSet. The compiler does not know how to convert the resulting SortedSet to your This subclass.

But if you upcast to the SortedSetLike trait the compiler will find its empty method which returns a This.



来源:https://stackoverflow.com/questions/31080332/why-is-upcasting-necessary-in-this-scala-code

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