这个转换为子类型安全吗?

时间:2016-09-24 03:22:36

标签: scala

鉴于这些类和变量:

abstract class Base[T <: Base[_]] {
  val self: T
  def me(): T = self
}

class Derived extends Base[Derived] {
  lazy val self = this
  def whoAmI() = "Im derived"
}

val d = new Derived

我可以安全地拨打d.foo().whoAmI()

但这也是类型安全吗?

abstract class Base[T <: Base[_]] {
  def me(): T = this.asInstanceOf[T]
}

class Derived extends Base[Derived] {
  def whoAmI() = "Im derived"
}

我正在考虑边缘情况,其中其他类从Derived扩展而且强制转换可能会爆炸

1 个答案:

答案 0 :(得分:4)

它不是类型安全的。如果您发现需要使用asInstanceOf进行编译,那么答案绝对是“不”。如果只有一个子类型,唯一一次“安全”转换为子类型。否则,你无法做出任何保证。

考虑这个例子:

abstract class Base[T <: Base[_]] {
  def me(): T = this.asInstanceOf[T]
}

class A extends Base[A]
class B extends Base[A]

scala> val b = new B
b: B = B@4b44655e

scala> b.me
java.lang.ClassCastException: B cannot be cast to A
  ... 33 elided

我们扩展的T中的Base必须与我们正在创建的子类型相同,只是它们都扩展Base没有限制。 AB都是Base[_],但B不是A,因此投放到A会不安全。

这很容易通过在Base中引入自我类型来解决,这需要它也是T。然后,我们可以确定thisT并且不需要投射。

abstract class Base[T <: Base[_]] { this: T =>
  def me(): T = this
}

这将不再编译:

scala> class B extends Base[A]
<console>:12: error: illegal inheritance;
 self-type B does not conform to Base[A]'s selftype A
       class B extends Base[A]
                       ^