2017-05-18 6 views
2

共変ジェネリックのオーダード特性にはミックスミックスがありますか?共変(covariant)ジェネリックで修飾された形質を実装する

私は、次のコードを持っている:私はT共変を必要とあまりにも動作するように命じたい

trait Foo[+T <: Foo[T]] extends Ordered[T] { 

    def id: Int 

    override def compare(that : T) : Int = { 
    this.id compare that.id 
    }  
} 

を。上記のバージョンは、 "反変的位置エラーの共変型"を示しています。

答えて

3

それは反変な位置にジェネリック型を必要とするため、あなたが共変タイプでOrderedを使用することはできません。代わりに、あなたはコンパニオンオブジェクト

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

Ordered[A]Aで不変である。 The old documentation for this trait explains why

完全に順序付けられたデータの特性。バージョン2006-07-24以降、この特性はもはやaで共変ではないことに注意してください。 Ordered [A]のインスタンスに対するequalsメソッドは、compareメソッドと一貫していることが重要です。しかし、タイプ消去のセマンティクスに固有の制限のため、Ordered [A]のインスタンスに対して、デフォルトの等価実装を提供する合理的な方法はありません。したがって、Ordered [A]のインスタンスで平等を使用できるようにする必要がある場合は、インスタンス化またはインスタンス化するときに自分で提供する必要があります。 Ordered [A]のインスタンスのhashCodeメソッドがcompareメソッドと一貫していることが重要です。しかし、わかりやすいデフォルト実装を提供することはできません。したがって、Ordered [A]のインスタンスのハッシュを計算できるようにする必要がある場合は、インスタンス化またはインスタンス化するときに自分で指定する必要があります。

これはOrdered[A]を使用したい場合は、明示的Fooのサブタイプのためcompareの実装を提供する必要がありますを意味します。

この問題を回避するには、暗黙のOrdering[A]で行うことができます。

implicit def ord[A <: Foo[A]] = new math.Ordering[A] { 
    override def compare(a: A, b: A) = a.id compare b.id 
} 
関連する問題