为什么在此Scala代码中需要向上转换?

Rob*_*een 11 scala upcasting scala-collections

这编译:

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

}
Run Code Online (Sandbox Code Playgroud)

但如果删除了upcast,则无法编译:

import scala.collection._

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

  def bar: This = this.empty

}
Run Code Online (Sandbox Code Playgroud)

为什么?从extends我们知道的子句Foo是a SortedSetLike[A, This],所以upcast当然是有效的 - 但是这不表明编译器允许发生冲突的继承吗?

小智 6

SortedSetLike特征继承了SetLike方法。

/** The empty set of the same type as this set
* @return  an empty set of type `This`.
*/
def empty: This
Run Code Online (Sandbox Code Playgroud)

SortedSet重写了方法并具有显式返回类型:

/** Needs to be overridden in subclasses. */
override def empty: SortedSet[A] = SortedSet.empty[A]
Run Code Online (Sandbox Code Playgroud)

由于您指定This is a subclass of SortedSet ,编译器将首先找到SortedSet实现,它返回一个SortedSet。编译器不知道如何将生成的SortedSet转换为您的This子类。

但如果你向上转换为SortedSetLike特征,编译器会发现它的方法返回This