是否有一种混合使用协变特征的有序特征?
我有以下代码:
trait Foo[+T <: Foo[T]] extends Ordered[T] {
def id: Int
override def compare(that : T) : Int = {
this.id compare that.id
}
}
我需要T
协变的地方,并希望下令工作。上面的版本给出了逆变位置误差&#34;协变类型&#34;。
答案 0 :(得分:3)
您不能将Ordered
与协变类型一起使用,因为它需要在逆变位置使用泛型类型。相反,您应该使用随播对象
Ordering
trait Foo[+T] {
def id: Int
}
object Foo {
implicit def fooOrdering[A <: Foo[_]]: Ordering[A] = {
new Ordering[A] {
override def compare(x: A, y: A): Int = x.id compare y.id
}
}
}
比较对象的任何合理函数都应该在它正在比较的对象的Ordering实例中,并且许多隐式地执行。例如
case class F(id: Int) extends Foo[Int]
case class G(id: Int) extends Foo[Int]
List(F(1), F(2), F(5), F(3), G(12)).max // = G(12)
答案 1 :(得分:1)
Ordered[A]
在A
中不变。 The old documentation for this trait explains why:
完全有序数据的特征。请注意,自2006-07-24版本以来,此特征不再具有协变性。重要的是,Ordered [A]实例的equals方法与compare方法一致。但是,由于类型擦除语义中固有的限制,没有合理的方法为Ordered [A]的实例提供相等的默认实现。因此,如果您需要能够在Ordered [A]的实例上使用相等,则必须在iniririting或实例化时自己提供。重要的是,Ordered [A]实例的hashCode方法与compare方法一致。但是,不可能提供合理的默认实现。因此,如果您需要能够计算Ordered [A]实例的哈希值,则必须在启用或实例化时自行提供。
这意味着如果您想使用Ordered[A]
,则明确必须为compare
的子类型提供Foo
的实施。
可以使用隐式Ordering[A]
:
implicit def ord[A <: Foo[A]] = new math.Ordering[A] {
override def compare(a: A, b: A) = a.id compare b.id
}