Scala 类型参数的界定

时间:2022-04-27 23:11:53

<: - 上界

trait Similar {
def isSimilar(x: Any): Boolean
}
case class MyInt(x: Int) extends Similar {
def isSimilar(m: Any): Boolean =
m.isInstanceOf[MyInt] &&
m.asInstanceOf[MyInt].x == x
}
object UpperBoundTest extends App {
def findSimilar[T <: Similar](e: T, xs: List[T]): Boolean =
if (xs.isEmpty) false
else if (e.isSimilar(xs.head)) true
else findSimilar[T](e, xs.tail)
val list: List[MyInt] = List(MyInt(1), MyInt(2), MyInt(3))
println(findSimilar[MyInt](MyInt(4), list))
println(findSimilar[MyInt](MyInt(2), list))
}

>: - 下界

case class ListNode[+T](h: T, t: ListNode[T]) {
def head: T = h
def tail: ListNode[T] = t
def prepend[U >: T](elem: U): ListNode[U] =
ListNode(elem, this)
}
object LowerBoundTest extends App {
val empty: ListNode[Null] = ListNode(null, null)
val strList: ListNode[String] = empty.prepend("hello")
.prepend("world")
val anyList: ListNode[Any] = strList.prepend(12345)
}

<% - 视图界定(view bound)

视图定界是Scala引入的一种机制:它能确保类型A的使用就像类型B一样,基本语法如下:
def f[A <% B](a: A) = a.bMethod
换句话说,A能够隐式转换为B,所以A的对象能够调用B的方法。在Scala标准库(Scala 2.8.0以前)中视图定界通常是和Ordered连用,如:
def f[A <% Ordered[A]](a: A, b: A) = if (a < b) a else b
因为A能够转换为Order[A],Ordered[A]又定义了方法<(other: A): Boolean,所以可以使用表达式a<b。不过视图定界已经过期了,尽量避免使用。

: - 上下文界定(context bound)

上下文界定是Scala 2.8.0引入的,它描述的是隐式值,而非视图定界的隐式转换,用来声明某种类型A,那么就存在隐式类型B[A],基本语法如下:
def f[A : B](a: A) = g(a) // g需要类型为B[A]的隐式值
常用用法:

def f[A : ClassManifest](n: Int) = new Array[A](n)

def f[A : Ordering](a: A, b: A) = implicitly[Ordering[A]].compare(a, b)

def f[A : Ordering](a: A, b: A) = if (implicitly[Ordering[A]].lt(a, b)) a else b

def f[A : Numeric](a: A, b: A) = implicitly[Numeric[A]].plus(a, b)


参考资料

1、Scala中的协变,逆变,上界,下界等

2、scala雾中风景(10): 逆变点与协变点