【问题标题】:Why is upcasting necessary in this Scala code?为什么在这个 Scala 代码中需要向上转换?
【发布时间】:2015-06-26 18:58:50
【问题描述】:

这样编译:

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

}

但是如果删除了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

}

为什么?从extends 子句中,我们知道FooSortedSetLike[A, This],所以向上转换当然是有效的——但这是否表明编译器允许发生冲突继承?

【问题讨论】:

  • 我不知道这个案例的确切细节,但这是另一个可能发生的可怕事情的例子,因为子类中的方法可以具有比它们实现的方法签名更具体的返回类型。跨度>

标签: scala scala-collections upcasting


【解决方案1】:

SortedSetLike trait 继承了 SetLikeempty 方法。

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

但是 SortedSet 覆盖了 empty 方法并且有一个明确的返回类型:

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

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

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

【讨论】:

    猜你喜欢
    • 2021-12-12
    • 2015-01-01
    • 2016-06-18
    • 1970-01-01
    • 1970-01-01
    • 2017-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多