Вы можете определить структурный тип для 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
Шаблон класса типов использует границы контекста.Ищите это для получения дополнительной информации.Этот стиль обычно предпочтительнее прежнего стиля в настоящее время, потому что он более гибок во многих отношениях.Тем не менее, оба будут работать.
В этом случае можно использовать его так:
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"))
}