考虑这个(有点人为的)例子:
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
以某种方式失败。
答案 0 :(得分:6)
如果您的ClassCastException
子类不是TopLevel[A]
,那么您将获得A
。为了避免投射你需要使用自我类型(我不确定这是否是正确的名称):
abstract class TopLevel[A] extends Obj[A, A] {
this: A =>
def parent: A = this
}