上界
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]
隱式參數
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)
case class Pair[T](first:T,second:T){ def smaller(implicit ord : Ordering[T]) = ord.min(first,second) } case class Student(val id:Int,val name:String) object Student { implicit object StudentOrdering extends Ordering[Student] { override def compare(x: Student, y: Student): Int = x.id - y.id } } object ContextBound { def main(args: Array[String]): Unit = { val smaller = Pair(Student(1,"zhangsan"), Student(2,"lisi")).smaller println(smaller) } }
上下文界定
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 = 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 (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]
的一個子類型唐含。