Sto cercando di avvolgere la mia mente attorno a tipi di sé astratti ed espliciti in scala. Consente di considerare questo esempio: Voglio creare una base per l'albero estensibile semplice come questo:Tipo Scala di tipo e tipo this.type in collezioni
trait Tree {
def children: Iterable[Tree]
def descendants: Iterable[Tree] = { val dv = children.view; dv ++ (dv.flatMap { _.children }) }
}
Tuttavia, voglio essere in grado di estendere nodi dell'albero con alcuni metodi e utilizzare questi metodi come: tree.children foreach { _.newMethod() }
Per questo ho provato:
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 })
}
}
Lavorare variante a piuttosto maldestro.
B. I tipi astratti: 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 })
}
}
non funziona affatto a causa di percorso specifico tipo non corrispondente come ho capito.
C. Tipo params (generici): ok
trait Tree[+Node <: Tree[Node]] {
def children: Iterable[Node]
def descendants: Iterable[Node] = {
val dv = children.view
dv ++ (dv.flatMap { _.children })
}
}
funziona bene, ma non così buono da mantenere nelle classi derivate.
Qualche idea su come far funzionare le prime due varianti senza un sacco di codice?
Inoltre, con questo tipo di problemi ho riscontrato problemi con l'implementazione.
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 {
// ...
}
Grazie!
Ah sì. Il problema "Scala non ha MyType" di nuovo. –
come puoi vedere Ho dato un'occhiata a questo in SO, e ho provato le varianti proposte. funziona bene per costrutti abbastanza semplici (come 'c.incr(). decr()' esempio nel documento di Martin), ma con le raccolte no. – tuxSlayer
sì. capito il motivo per cui dopo aver letto la tua discussione qui http://www.scala-lang.org/node/6649, grazie – tuxSlayer