上界
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]
隱式參數(shù)
可以提供「隱式參數(shù)」,改善smaller
的設(shè)計。
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
編譯器實際調(diào)用:
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)
}
上例通過顯式地提供「隱式參數(shù)」尸红,當此手法成為一種實現(xiàn)模式時,Scala
很自然地引入了「上下文界定」榨呆。
implicitly
實用函數(shù)
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]
首先調(diào)用了object Ordering
的apply
方法,從而便捷地找到了Order[T]
的隱式值涤浇。
object Ordering {
def apply[T](implicit ord: Ordering[T]) = ord
}
所以Ordering[T].min
等價于implicitly[Ordering[T]].min
鳖藕。
視圖界定
如果使用Ordered
,及其「隱式參數(shù)」的機制只锭,smaller
可以實現(xiàn)為:
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
的局部作用域內(nèi)著恩,即是一個「隱式參數(shù)」,又是一個「隱式轉(zhuǎn)換函數(shù)」蜻展,從而設(shè)計可以簡化為:
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
的隱式轉(zhuǎn)換喉誊,而RichInt
是Ordered[Int]
的子類型;所以在Predef
定義的implicit Int => RichInt
的隱式轉(zhuǎn)換函數(shù)可作為隱式參數(shù)implicit order: T => Ordered[T]
的隱式值纵顾。
Pair(1, 2).smaller
等價于
Pair(1, 2).smaller(Predef.intWrapper _)
上述簡化的設(shè)計伍茄,使得隱式參數(shù)order
沒有必要存在,而且這樣的「實現(xiàn)模式」較為常見施逾,可歸一為一般模式:視圖界定敷矫。
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
可以隱式轉(zhuǎn)換為Ordered[T]
;而T <: Ordered[T]
表示:T
是Ordered[T]
的一個子類型汉额。