考虑这个(有些人为的)示例:

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是否会因某种原因而失败。

最佳答案

如果您的ClassCastException子类不是TopLevel[A],则将获得A。为了避免强制转换,您应该使用自我类型(我不确定这是否是正确的名称):

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

09-26 15:35