上界
case class Pair[T <: Comparable[T]](first: T, second: T) {
def smaller = if (first.compareTo(second) < 0) first else second
}
Pair("1", "2").smaller // OK, String is subtype of Comparable[String]
Pair(1, 2).smaller // Compile Error, Int is not subtype of Comparable[Int]
隐式参数
可以提供「隐式参数」,改善smaller的设计。
import scala.math.Ordering
case class Pair[T](first: T, second: T){
def smaller(implicit order: Ordering[T]) =
order.min(first, second)
}
当T为Int
Pair(1, 2).smaller
编译器实际调用:
Pair(1, 2).smaller(Ordering.Int)
其中Ordering.Int定义在Ordering的伴生对象中
object Ordering {
trait IntOrdering extends Ordering[Int] {
def compare(x: Int, y: Int) =
if (x < y) -1
else if (x == y) 0
else 1
}
implicit object Int extends IntOrdering
}
当T为自定义类型
import scala.math.Ordering
case class Point(x: Int, y: Int)
object Point {
implicit object point extends Ordering[Point] {
def compare(lhs: Point, rhs: Point): Int =
(lhs.x + lhs.y) - (rhs.x + rhs.y)
}
}
Pair(Point(0, 0), Point(1, 1)).smaller
等价于
Pair(Point(0, 0), Point(1, 1)).smaller(Point.point)
上下文界定
import scala.math.Ordering
case class Pair[T](first: T, second: T){
def smaller(implicit order: Ordering[T]) =
order.min(first, second)
}
上例通过显式地提供「隐式参数」,当此手法成为一种实现模式时,Scala很自然地引入了「上下文界定」。
implicitly实用函数
import scala.math.Ordering
case class Pair[T : Ordering](first: T, second: T) {
def smaller = implicitly[Ordering[T]].min(first, second)
}
其中,implicitly定义在Predef中,用于从「冥界」中提取T的隐式值。
def implicitly[T](implicit e: T) = e
更好、更漂亮
import scala.math.Ordering
case class Pair[T : Ordering](first: T, second: T) {
def smaller = implicitly[Ordering[T]].min(first, second)
}
可以进一步简化为:
import scala.math.Ordering
case class Pair[T : Ordering](first: T, second: T) {
def smaller = Ordering[T].min(first, second)
}
其中,Ordering[T]首先调用了object Ordering的apply方法,从而便捷地找到了Order[T]的隐式值。
object Ordering {
def apply[T](implicit ord: Ordering[T]) = ord
}
所以Ordering[T].min等价于implicitly[Ordering[T]].min。
视图界定
如果使用Ordered,及其「隐式参数」的机制,smaller可以实现为:
import scala.math.Ordered
case class Pair[T](first: T, second: T) {
def smaller(implicit order: T => Ordered[T]) = {
if (order(first) < second) first else second
}
}
implicit order: T => Ordered[T]在smaller的局部作用域内,即是一个「隐式参数」,又是一个「隐式转换函数」,从而设计可以简化为:
import scala.math.Ordered
case class Pair[T](first: T, second: T) {
def smaller(implicit order: T => Ordered[T]) = {
if (first < second) first else second
}
}
又因为在Predef预定义了从Int到RichInt的隐式转换,而RichInt是Ordered[Int]的子类型;所以在Predef定义的implicit Int => RichInt的隐式转换函数可作为隐式参数implicit order: T => Ordered[T]的隐式值。
Pair(1, 2).smaller
等价于
Pair(1, 2).smaller(Predef.intWrapper _)
上述简化的设计,使得隐式参数order没有必要存在,而且这样的「实现模式」较为常见,可归一为一般模式:视图界定。
import scala.math.Ordered
case class Pair[T <% Ordered[T]](first: T, second: T) {
def smaller = if (first < second) first else second
}
注意:T <% Ordered[T]表示:T可以隐式转换为Ordered[T];而T <: Ordered[T]表示:T是Ordered[T]的一个子类型。