在这个使用泛型的例子中,asInstanceOf有什么问题吗?

Mic*_*jac 3 generics scala

考虑这个(有点人为的)例子:

abstract class Obj[A, B] {
    def id: Long
    def parent: B
}

abstract class TopLevel[A] extends Obj[A, A] {
    def parent: A = this.asInstanceOf[A] // How terrible is this?
}

abstract class AbsChild[A, B] extends Obj[A, B] {
    def parent: B
}

case class Top(id: Long) extends TopLevel[Top]

case class Child(id: Long, parent: Top) extends AbsChild[Child, Top]
Run Code Online (Sandbox Code Playgroud)

为了描绘更好的图片,想象一下AbsChild文件系统上的某种目录,以及TopLevelAbsChild所属的物理驱动器.所以parent实际上并不是指对象的直接父级(比如包含它的目录),而是引用树中的顶级对象.

在某些应用程序中,我将要处理a List[Obj[A, B]],而不是立即知道它是什么Obj.在这种情况下,即使a TopLevel拥有a 也会很好parent,它应该只返回对自身的引用.这就是我的问题.

定义def parent: A = thisTopLevel不工作:

<console>:14: error: type mismatch;
 found   : TopLevel.this.type (with underlying type TopLevel[A])
 required: A
Run Code Online (Sandbox Code Playgroud)

def parent: A = this.asInstanceOf[A]确实,并且似乎在实践中正确运作.

scala> val top = Top(1)
top: Top = Top(1)

scala> val child = Child(1, top)
child: Child = Child(1,Top(1))

scala> top.parent
res0: Top = Top(1)

scala> child.parent
res1: Top = Top(1)
Run Code Online (Sandbox Code Playgroud)

但这真的没问题吗?使用asInstanceOf[A]感觉非常脏,并让我想知道它是否会以某种方式失败ClassCastException.

lmm*_*lmm 6

ClassCastException如果你有一个TopLevel[A]不是的子类,你会得到一个A.为了避免需要施放你应该使用自我类型(我不确定这是否是正确的名称):

abstract class TopLevel[A] extends Obj[A, A] {
  this: A =>
    def parent: A = this
}
Run Code Online (Sandbox Code Playgroud)