Tôi đang cố gắng để quấn đầu của tôi xung quanh trừu tượng và rõ ràng loại tự trong scala. Hãy xem xét ví dụ sau: Tôi muốn tạo ra một cơ sở cho cây mở rộng đơn giản như này:Scala tự loại và this.type trong bộ sưu tập vấn đề
trait Tree {
def children: Iterable[Tree]
def descendants: Iterable[Tree] = { val dv = children.view; dv ++ (dv.flatMap { _.children }) }
}
Tuy nhiên, tôi muốn để có thể mở rộng các nút cây với một số phương pháp và sử dụng các phương pháp như: tree.children foreach { _.newMethod() }
Đối với điều này tôi đã cố gắng:
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 })
}
}
Làm việc biến một lại khá vụng về.
B. Tóm tắt loại: 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 })
}
}
Không làm việc ở tất cả do đường dẫn cụ thể loại không phù hợp như tôi hiểu.
C. Loại params (generics): OK
trait Tree[+Node <: Tree[Node]] {
def children: Iterable[Node]
def descendants: Iterable[Node] = {
val dv = children.view
dv ++ (dv.flatMap { _.children })
}
}
trình OK, nhưng không quá tốt để duy trì trong các lớp thừa kế.
Bất kỳ ý tưởng nào về cách tạo hai biến thể đầu tiên hoạt động mà không cần tấn mã?
Ngoài ra, với this.type tôi đã gặp sự cố khi triển khai.
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 {
// ...
}
Cảm ơn!
Ah vâng. Vấn đề "Scala không có MyType" một lần nữa. –
như bạn có thể thấy tôi đã xem xét điều này trong SO và đã thử các biến thể được đề xuất. nó hoạt động tốt cho các cấu trúc khá đơn giản (ví dụ như 'c.incr(). decr()' ví dụ trong bài báo của Martin), nhưng với các bộ sưu tập thì không. – tuxSlayer
vâng. có lý do tại sao sau khi đọc thảo luận của bạn ở đây http://www.scala-lang.org/node/6649, cảm ơn – tuxSlayer