Scala在抽象类型中隐式排序

时间:2016-10-05 09:18:14

标签: scala

我在抽象类中有一个泛型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.

2 个答案:

答案 0 :(得分:3)

不幸的是,您无法使用抽象类型实现此目的。要制作依赖于隐式参数compile的通用代码,您需要一个上下文绑定,并且上下文边界只能作为类型参数传递。

在这里,我将您的抽象类型移动到一个类型参数中并添加了一个上下文绑定(注意构造函数中传递的隐式参数):

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,以便有一种方法可以按它排序。

答案 1 :(得分:0)

你可以添加缺失的隐含:它也可以是抽象的。

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

当然,这种方法的问题在于使用它最终会比谢尔盖的回答更加丑陋:

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)]],你将进入一个无限循环,需要手动建立排序。