Reputation: 1935
I am trying to make a trait which I can mixing to an class to define it as a tree node. Finding an elegant way of doing this is turning out to be problematic.
The following just doesn't work, as this.type causes a type mismatch when you assign a parent
trait Node {
def parent:Option[this.type]
def root:this.type =
parent.fold(this)(_.root)
}
This kind of works but the T value could get miss-assigned, and the casting is pretty ugly.
trait Node[T <: Node[T]] {
def parent:Option[T]
def root:T =
parent.fold(this)(_.root).asInstanceOf[T]
}
Any ideas of a stricter approach?
Upvotes: 0
Views: 90
Reputation: 9137
You can add a self-type to avoid the cast:
trait Node[T <: Node[T]] { self: T =>
def parent: Option[T]
def root: T = parent.fold(this)(_.root)
}
You can additionally return T with Node[T]
instead of plain T
, but I'm not sure if that gives real benefits beyond what the self-type gives you:
trait Node[T <: Node[T]] { self: T =>
def parent: Option[T with Node[T]]
def root: T with Node[T] = parent.fold(this)(_.root)
}
Upvotes: 2
Reputation: 62835
trait Node[+T] {
def parent: Option[Node[T]]
def root: Node[T] = parent.fold(this)(_.root) // root is node as well, isn't it?
}
class Foo extends Node[Foo] { def parent = None }
Upvotes: 3