您可以为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
这使用了所谓的view bound。查找更多信息,但足以说明您将能够处理任何定义了隐式转换并在范围内的东西,就好像它是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
类型类模式使用上下文边界。查找更多信息。如今,这种风格通常比以前的风格更受欢迎,因为它在许多方面都更加灵活。不过,两者都可以。
在这种情况下,可以这样使用它:
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"))
}