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

时间:2014-12-18 16:36:21

标签: scala generics

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

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]

要绘制更好的图片,请将AbsChild设想为文件系统上的某种目录,将TopLevel设置为AbsChild所属的物理驱动器。所以parent实际上并不是指对象的直接父级(如包含它的目录),而是引用树中的顶级对象。

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

def parent: A = this定义TopLevel不起作用:

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

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)

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

1 个答案:

答案 0 :(得分:6)

如果您的ClassCastException子类不是TopLevel[A],那么您将获得A。为了避免投射你需要使用自我类型(我不确定这是否是正确的名称):

abstract class TopLevel[A] extends Obj[A, A] {
  this: A =>
    def parent: A = this
}