考虑这个(有些人为的)示例:
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
}