tux*_*yer 9 scala self-type abstract-type
我试图在scala中围绕抽象和显式自我类型.让我们考虑这个例子:我想为可扩展树创建一个简单的基础:
trait Tree {
def children: Iterable[Tree]
def descendants: Iterable[Tree] = { val dv = children.view; dv ++ (dv.flatMap { _.children }) }
}
Run Code Online (Sandbox Code Playgroud)
但是,我希望能够使用某些方法扩展树节点并使用以下方法: tree.children foreach { _.newMethod() }
为此,我尝试过:
A. this.type:失败
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 })
}
}
Run Code Online (Sandbox Code Playgroud)
工作变体非常笨拙.
B.摘要类型:失败
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 })
}
}
Run Code Online (Sandbox Code Playgroud)
根据我的理解,由于路径特定类型不匹配,根本不起作用.
C.类型params(泛型):好的
trait Tree[+Node <: Tree[Node]] {
def children: Iterable[Node]
def descendants: Iterable[Node] = {
val dv = children.view
dv ++ (dv.flatMap { _.children })
}
}
Run Code Online (Sandbox Code Playgroud)
工作正常,但在派生类中维护不太好.
任何想法如何使前两个变体工作没有大量的代码?
另外,使用this.type我遇到了实现问题.
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 {
// ...
}
Run Code Online (Sandbox Code Playgroud)
谢谢!
如果没有真正理解你遇到的问题(C),你可以尝试(B)的变体:
trait Tree {
type Node <: Tree
def children: Iterable[Tree#Node]
def descendants: Iterable[Tree#Node] = {
val dv = children.view
dv ++ (dv.flatMap { _.children })
}
}
Run Code Online (Sandbox Code Playgroud)
这避免了您的路径特定类型问题.顺便说一下,你应该看看http://www.assembla.com/spaces/scala-graph/wiki
最后,我解决了本次讨论中提出的问题http://www.scala-lang.org/node/6649:
trait Tree[+Node <: Tree[Node]] {
this: Node =>
def children: Iterable[Node]
def descendants: Iterable[Node] = {
val dv = children.view
dv ++ (dv.flatMap { _.children })
}
}
Run Code Online (Sandbox Code Playgroud)
即变体(C),但具有明确的自我类型。this这提供了在其他方法(例如 method )中使用的机会find(path: String): Option[Node]。
| 归档时间: |
|
| 查看次数: |
414 次 |
| 最近记录: |