Estoy tratando de entender los auto tipos abstractos y explícitos en scala. Vamos a considerar este ejemplo: Quiero crear una base para el árbol extensible tan simple como esto:auto tipo Scala y this.type in collections issue
trait Tree {
def children: Iterable[Tree]
def descendants: Iterable[Tree] = { val dv = children.view; dv ++ (dv.flatMap { _.children }) }
}
Sin embargo, quiero ser capaz de extender los nodos del árbol con algunos métodos y utilizar estos métodos como: tree.children foreach { _.newMethod() }
Para ello he intentado:
A. this.type fall
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 })
}
}
Trabajando una variante re bastante torpe
B. Resumen tipos fall
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 })
}
}
no funciona en absoluto debido a camino de coincidencia de tipos específicos que he entendido.
params C. Tipo (genéricos): OK
trait Tree[+Node <: Tree[Node]] {
def children: Iterable[Node]
def descendants: Iterable[Node] = {
val dv = children.view
dv ++ (dv.flatMap { _.children })
}
}
funciona bien, pero no tan bueno para mantener en las clases derivadas.
¿Alguna idea de cómo hacer que las dos primeras variantes funcionen sin toneladas de código?
Además, con this.type me he encontrado con problemas con la implementación.
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 {
// ...
}
¡Gracias!
Ah sí. El problema "Scala no tiene MyType" otra vez. –
como puedes ver, eché un vistazo a esto en SO, y probé las variantes propuestas. funciona bien para construcciones bastante simples (como 'c.incr(). decr()' ejemplo en el documento de Martin), pero con colecciones no lo hace. – tuxSlayer
sí. entendió por qué después de leer su discusión aquí http://www.scala-lang.org/node/6649, gracias – tuxSlayer