Is there something wrong with asInstanceOf in this example using generics?

Consider this (somewhat contrived) example:

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]

      

To paint the best picture, think of it AbsChild

as a kind of directory on the file system and TopLevel

as the physical disk to which it belongs AbsChild

. So it parent

doesn't really refer to the direct parent object (like the directory that contains it), but rather a reference to the top-level object in the tree.

In some applications I will deal with List[Obj[A, B]]

where it is not immediately known what it is Obj

. In this case, it would be nice if it even TopLevel

had an a parent

that should just return a reference to itself. And that is my question.

Definition def parent: A = this

for TopLevel

doesn't work:

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

      

But def parent: A = this.asInstanceOf[A]

does and seems to work correctly in practice.

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)

      

But is it really good? The use asInstanceOf[A]

feels incredibly messy and leaves me wondering if it won't work with ClassCastException

.

+3


source to share


1 answer


You would get ClassCastException

if you had a subclass TopLevel[A]

that didn't A

. To avoid having to cast, you should use the self type (I'm not sure if that's the correct name):



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

      

+6


source







All Articles