2016-10-05 15 views
0

抽象クラスにジェネリックTのリストがあります。抽象的な型の暗黙の順序付け

abstract class MyAbstractClass[T] { 
    type SortOrder 
    def getSorterFunc(): T => SortOrder 

    def sort(myList: List[T]) = { 
    val sortFunc = getSorterFunc() 
    myList.sortBy(sortFunc) 
    } 
} 

object SampleObject extends MyAbstractClass[(String,Int,List[Int])] { 
    type SortOrder = (String,Int) 

    override def getSorterFunc(): (String,Int,List[Int]) => SortOrder { 
    val sortFunc : (String,Int,List[Int]) => SortOrder = { 
      case (username, id, addresses) => (username, id) 
     } 
    sortFunc 
    } 
} 

抽象クラスから多くの派生クラスがあります。 リスト[T]でカスタムソートを行いたい。これを達成する方法は? 上記のコードはコンパイルエラーをスローします。

No implicit Ordering defined for MyAbstractClass.this.SortOrder. 
+0

一見すると、 'getSorterFunc'は' SampleObject'に定義されていない 'T'を返すので、これはどのようにコンパイルすることができません。 – slouc

+0

これは間違いです。私はそれを修正しました。 – Knight71

答えて

3

残念ながら、抽象的なタイプではこれを達成できません。暗黙的なパラメータに依存するジェネリックコードをコンパイルするには、コンテキストバインドが必要であり、コンテキスト境界は型パラメータとして渡すことしかできません。ここで

は、私は(コンストラクタで渡された暗黙のパラメータに注意してください)typeパラメータにあなたの抽象型を移動し、バインドされたコンテキストを追加しました:

abstract class MyAbstractClass[T, SortOrder](implicit ord: Ordering[SortOrder]) { 

    def getSorterFunc(): (T) => SortOrder 

    def sort(myList: List[T]) = { 
    val sortFunc = getSorterFunc() 
    myList.sortBy(sortFunc) 
    } 
} 

object SampleObject extends MyAbstractClass[(String, Int, List[Int]), (String, Int)] { 
    def getSorterFunc() = { 
    case (username, id, addresses) => (username, id) 
    } 
} 

コンパイラが知っているこの方法を事前にMyAbstractClassの任意のサブクラスということにはがあり、それによって並べ替える方法があるようにそのSortOrderを定義しています。

+0

素晴らしい!私はクラス内で暗黙のordをやっていた。 – Knight71

0

暗黙的に欠けている部分を追加するだけで、抽象的にすることもできます。

object SampleObject extends MyAbstractClass[(String, Int, List[Int])] { 
    type SortOrder = (String, Int) 
    val ordering = implicitly[Ordering[(String, Int)]] 
    override def getSorterFunc() = { 
    val sortFunc: ((String, Int, List[Int])) => SortOrder = { 
     case (username, id, addresses) => (username, id) 
    } 
    sortFunc 
    } 
} 

プラスあなたはimplicit val ordering = implicitly[Ordering[(String, Int)]]を書いた場合、あなたは無限に取得します:もちろん

abstract class MyAbstractClass[T] { 
    type SortOrder 
    implicit val ordering: Ordering[SortOrder] 
    def getSorterFunc(): T => SortOrder 

    def sort(myList: List[T]) = { 
    val sortFunc = getSorterFunc() 
    myList.sortBy(sortFunc) 
    } 
} 

は、このアプローチの問題点は、セルゲイの答えの1よりも醜い終わる使用していることです代わりに手動でオーダリングを構築する必要があります。

関連する問題