您可以爲key
定義結構類型,但不適用於union
。結構類型可能不涉及自身之外定義的抽象類型。所以這是行不通的:
trait Tree[T <: { def union(x: T): T }]
你可以定義一個特質是的Tree
元素必須可用,但:
trait TreeVal[T] {
type A
def key: A
def union(x: T): T
}
這可以採用兩種方法。首先,這些類必須實現該接口,這會嚴重限制哪些類可以用作關鍵字。這將是這樣的:
trait Tree[T <: TreeVal[T]]
它也可以提供作爲一個隱式轉換,就像這樣:
class IntVal(v: Int) extends TreeVal[Int] {
type A = Int
def key: A = v
def union(x: Int): Int = x + v
}
implicit def IntIsVal(v: Int): IntVal = new IntVal(v)
class Tree[T <% TreeVal[T]] // must be class, so it can receive parameters
該使用什麼叫做約束一個視圖。仔細查看,瞭解更多信息,但足以說您可以對任何具有已定義的隱式轉換的內容進行處理,並且範圍就好像它是TreeVal
。例如:
class Tree[T <% TreeVal[T]](node: T, left: Option[Tree[T]], right: Option[Tree[T]]) {
override def toString = "(%s < %s > %s)" format (left.getOrElse("o"), node.key, right.getOrElse("o"))
}
或者,你可以用型類模式使用它,有幾個變化:
trait TreeVal[T] {
type A
def key(v: T): A
def union(x: T, y: T): T
}
class Tree[T : TreeVal] // must be class, so it can receive parameters
Type類模式使用的上下文範圍。查看更多信息。這種風格通常比現在的風格更受歡迎,因爲它在很多方面都更加靈活。不過,兩者都會起作用。
在這種情況下,人們會使用這樣的:
implicit object IntVal extends TreeVal[Int] {
type A = Int
def key(v: Int) = v
def union(x: Int, y: Int) = x + y
}
class Tree[T: TreeVal](node: T, left: Option[Tree[T]], right: Option[Tree[T]]) {
val treeVal = implicitly[TreeVal[T]]
import treeVal._
override def toString = "(%s < %s > %s)" format (left.getOrElse("o"), key(node), right.getOrElse("o"))
}
優秀的解釋,非常感謝! – newf
但是還有一個問題:爲什麼我應該在'implicit object IntVal'中顯式指定'type A'?它可以從'def key'定義中推斷出來嗎? – newf
也許你可以使用'key'方法的參數化版本:'def key [A]:A' – incrop