Generics Scala泛型:Int不符合Comparable?
以下Scala声明是可以的:Generics Scala泛型:Int不符合Comparable?,generics,scala,int,comparable,Generics,Scala,Int,Comparable,以下Scala声明是可以的: trait Base[B <: Base[B,M,ID], M <: Meta[B,M,ID], ID <: Comparable[ID]] { // ... } trait Meta[B <: Base[B,M,ID], M <: Meta[B,M,ID], ID <: Comparable[ID]] extends Ordered[Meta[_,_,_]] { // ... } trait BaseWith
trait Base[B <: Base[B,M,ID], M <: Meta[B,M,ID], ID <: Comparable[ID]] {
// ...
}
trait Meta[B <: Base[B,M,ID], M <: Meta[B,M,ID], ID <: Comparable[ID]] extends Ordered[Meta[_,_,_]] {
// ...
}
trait BaseWithID[B <: BaseWithID[B,M,ID], M <: Meta[B,M,ID], ID <: Comparable[ID]] extends Base[B,M,ID] with Ordered[B] {
// ...
}
trait BaseWithIntID[B <: BaseWithIntID[B,M,ID], M <: MetaWithIntID[B,M,ID], ID <: Comparable[ID]] extends BaseWithID[B,M,ID] {
// ...
}
trait MetaWithIntID[B <: BaseWithIntID[B,M,ID], M <: MetaWithIntID[B,M,ID], ID <: Comparable[ID]] extends Meta[B,M,ID] {
// ...
}
“这是否意味着Int在Scala中不可比较?”的答案显然是肯定的,因为如果我用java.lang.Integer替换Int,那么它编译时不会出错。问题是,每次访问ID时,我都必须创建一个包装器对象,这将经常发生,因此代价高昂
我想指定ID是可比较的/有序的,这样我就可以对BaseWithID本身进行排序,并使用可比较的ID在其中显式定义比较方法
目前的解决方案似乎是不指定ID是有序的,而是让具体类实现自身比较,而不是在trait中一次性实现它。有谁有更好的解决方案吗?Int在scala中确实是不可比的,因为它实际上是作为java
Int
实现的,而不是java.lang.Integer
。我不确定这是不可能的,C#struct
(值类型)可以实现接口,但这里没有实现
您通常会说,在ID类型的隐式作用域中有一个排序
,使用ID:Ordering
举个简单的例子:
import Ordering.Implicits._
def max[A : Ordering](x: A, y: A) : A = if (x > y) then x else y
这相当于将排序(与java.util.Comparator
相同)传递给函数。事实上,《宣言》
def max[A : Ordering](x: A, y: A)
转化为
def max[A](x: A, y: A)(implicit ev: Ordering[A])
其中,ev
是一个新名称。如果:Ordering出现在类而不是方法定义上,就像在代码中一样,它将转换为构造函数的隐式参数,如果需要,该参数将保留在字段中,并在类的隐式范围中可用。这比强制A具有可比性(在scala中排序)更灵活,因为它可以用于非您的类,并且没有实现可比性。您也可以在同一类上的不同排序之间进行选择,如果只需反转默认的排序:在排序
上有一个def reverse:Ordering
方法,它就是这样做的
坏的方面是,VM不太可能内联调用比较方法,但在泛型中使用接口方法也不太可能
在java中实现Comparable
的类型通过对象排序
中的隐式方法(ordered
)在隐式范围内自动获得排序
。java比较器
也可以转换为排序
(排序.比较器排序
)
导入Ordering.Implicits.\uu当排序[A]
在隐式范围内时,允许使用nicex>y
语法 为了补充我的答案,在“昂贵”方面,对比较方法Ordering.comare(x,y)的调用可能不会内联,您可能也需要付费。因此,在java中,它将具有可比性。另一方面,可以调用x>y的包装意味着新的order.Ops(x)。>(y),从实现的角度来看,它是新的Ordering.Ops(ord,x),其中ord是排序。很可能可以避免创建此对象。如果需要(基准测试),您可以直接调用ordering.compare,这不会比在java.P.S中调用compare更糟糕。“可能避免创建此对象”表示“可能VM实际上不会创建此对象”。这不仅是可能的,而且可以肯定的是,您可以通过不使用x>y语法来避免对象的创建
import Ordering.Implicits._
def max[A : Ordering](x: A, y: A) : A = if (x > y) then x else y
def max[A : Ordering](x: A, y: A)
def max[A](x: A, y: A)(implicit ev: Ordering[A])