您可以将Ordering[T]类型类用作隐式参数。如果你想写一个通用的 max 函数,它看起来像这样:
def max[T](a:T, b:T)(implicit ordering:Ordering[T]) = {
if(ordering.gt(a,b)) a else b
}
对于 Int、Float 等原始数据类型,范围内有一个隐式 Ordering[T],因此您可以按预期使用它。
max(1,2) // gives 2
对于所有实现 Ordered[T] 的类型,还有一个隐式提供 Ordering[T]。
范围内还有各种组合排序的方法。例如,如果您有一个 N 元组,其中每个元素都有一个 Ordering[T],则该元组类型会自动存在一个 Ordering。
max((1,2), (3,4)) // gives (3,4) because 3 is larger than 1
但是,如果您对任何隐式提供的排序不满意,您可以编写自己的并显式传递它,甚至将其作为隐式 val 获取。像这样:
val negativeIntOrdering = new Ordering[Int] {
def compare(a:Int,b:Int) = b - a
}
max(1,2)(negativeIntOrdering) // gives 1
所以基于类型类的方法比基于继承的方法灵活得多。这就是为什么像spire这样的数学库广泛使用它的原因。
上面的代码不太好的一件事是您必须使用 lt 方法而不是运算符。但也有解决方案。Ordering 有一个名为 mkOrderingOps 的隐式方法,它为 T 提供运算符。您只需通过导入 ordering._ 将其置于范围内,如下所示:
def max[T](a:T, b:T)(implicit ordering:Ordering[T]) = {
import ordering._;
if(a>b) a else b
}