Knight71 Knight71 - 1 month ago 11
Scala Question

Scala implicit ordering in abstract type

I have a list of generics T in a abstract class.

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
}
}


There can be many derived classes from the abstract class.
I want to do a custom sorting on the list[T]. How to achieve this ?
The above code throws compilation error.

No implicit Ordering defined for MyAbstractClass.this.SortOrder.

Answer

Unfortunately you cannot achieve this with abstract types. To make generic code that relies on implicit parameters compile, you'd need a context bound, and context bounds can only be passed as type parameters.

Here, I moved your abstract type into a type parameter and added a context bound (note the implicit parameter passed in the constructor):

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)
  }
}

This way the compiler knows in advance that any subclass of MyAbstractClass has to define its SortOrder such that there's a way to sort by it.

Comments