我有一个参数化类型的类,我想做比较运算符.我认为我需要使用Ordered trait来实现这一点,但编译器不喜欢我使用它.所以说我有以下课程:
class Test[T <: Ordered[T]] {
def someOp(t: T) if(t < 3) ...
...
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试使用此类如下:
val test = new Test[Int]()
Run Code Online (Sandbox Code Playgroud)
编译器抱怨如下:
类型参数[Test [Int]]不符合类Test的类型参数bounds [T <:Ordered [T]]
有人可以向我解释我在这里做错了什么吗?
thS*_*oft 22
发生这种情况是因为Int它不是Ordered[Int](看这里的原因)的子类.
但是,存在一个隐式强制Int,RichInt它是一个子类Ordered[Int],但它不是为下界触发的.使用<%(视图边界)而不是考虑隐式强制:
class Test[T <% Ordered[T]]
Run Code Online (Sandbox Code Playgroud)
Rüd*_*ehn 11
您可以使用Ordering [T]类型类作为隐式参数.如果你想编写泛型max函数,它看起来像这样:
def max[T](a:T, b:T)(implicit ordering:Ordering[T]) = {
if(ordering.gt(a,b)) a else b
}
Run Code Online (Sandbox Code Playgroud)
对于原始数据类型,如Int,Float,...,范围内有一个隐式的Ordering [T],以便您可以像预期的那样使用它.
max(1,2) // gives 2
Run Code Online (Sandbox Code Playgroud)
对于实现Ordered [T]的所有类型,还有一个隐式提供Ordering [T].
范围内还有各种方法可以组合排序.例如,如果你有一个N元组,其中每个元素都有一个Ordering [T],那么自动存在一个元组类型的Ordering.
max((1,2), (3,4)) // gives (3,4) because 3 is larger than 1
Run Code Online (Sandbox Code Playgroud)
但是如果你对任何隐式提供的排序不满意,你可以自己编写并明确地传递它,或者甚至将它作为隐式val在范围内获得.像这样:
val negativeIntOrdering = new Ordering[Int] {
def compare(a:Int,b:Int) = b - a
}
max(1,2)(negativeIntOrdering) // gives 1
Run Code Online (Sandbox Code Playgroud)
因此基于类型的方法比基于继承的方法更灵活.这就是像spire这样的数学库广泛使用它的原因.
上面代码不太好的一件事是你必须使用lt方法而不是运算符.但也有一个解决方案.Ordering有一个名为mkOrderingOps的隐式方法,为T提供运算符.你只需要通过导入orders._来获取它,如下所示:
def max[T](a:T, b:T)(implicit ordering:Ordering[T]) = {
import ordering._;
if(a>b) a else b
}
Run Code Online (Sandbox Code Playgroud)