Próbuję owijać głowę wokół abstrakcyjnych i jawnych typów siebie w scala. Rozważmy następujący przykład: Chcę stworzyć bazę dla rozszerzalny drzewa tak proste, jak to:Scala self type i this.type w kolekcjach wydanie
trait Tree {
def children: Iterable[Tree]
def descendants: Iterable[Tree] = { val dv = children.view; dv ++ (dv.flatMap { _.children }) }
}
Jednakże chcę, aby móc rozszerzyć węzły drzewa z niektórych metod i korzystać z tych metod, takich jak: tree.children foreach { _.newMethod() }
Do tego próbowałem:
A. this.type: FAIL
trait Tree {
def children: Iterable[this.type]
def descendants: Iterable[this.type] = {
val dv = children.view
// FAIL: type mismatch; found : scala.collection.IterableView[com.abovobo.data.Tree,Iterable[_]] required: Iterable[Tree.this.type]
// dv ++ (dv.flatMap { _.children })
// OK:
dv.++[this.type, Iterable[this.type]](dv.flatMap[this.type, Iterable[this.type]]{ _.children })
}
}
Praca wariant A jestem całkiem niezgrabny.
B. abstrakcyjne typy: FAIL
trait Tree {
type Node <: Tree
def children: Iterable[Node]
def descendants: Iterable[Node] = {
val dv = children.view
// FAIL: type mismatch; found : scala.collection.IterableView[com.abovobo.data.Tree#Node,Iterable[_]] required: Iterable[Tree.this.Node]
dv ++ (dv.flatMap { _.children })
}
}
nie działa w ogóle z powodu niedopasowania ścieżki konkretnego typu jak zrozumiałem.
C. Rodzaj params (rodzajów): OK
trait Tree[+Node <: Tree[Node]] {
def children: Iterable[Node]
def descendants: Iterable[Node] = {
val dv = children.view
dv ++ (dv.flatMap { _.children })
}
}
działa OK, ale nie tak dobre, aby utrzymać w klasach pochodnych.
Jakieś pomysły, jak zrobić pierwsze dwa warianty pracy bez mnóstwa kodu?
Również z tym typem mam problemy z implementacją.
trait BiDTree extends Tree {
def parent: Option[this.type]
}
// how to accept this param? Option[TreeImpl] doesn't work.
class TreeImpl(val parent: Option[???]) extends BiDTree {
// ...
}
Dzięki!
Ah tak. Problem "Scala nie ma MyType". –
jak widać, rzuciłem okiem na to w SO i wypróbowałem proponowane warianty. działa dobrze dla całkiem prostych konstrukcji (jak np. 'c.incr(). decr()' w artykule Martina), ale z kolekcjami tak nie jest. – tuxSlayer
tak. zrozumiałeś dlaczego po przeczytaniu twojej dyskusji http://www.scala-lang.org/node/6649, dziękuje – tuxSlayer