定义了扩展 Ordering[A] 的类 A 和 A 的子类 B 后,如何自动对 B 数组进行排序? Scala 编译器提示它“找不到参数 ord 的隐式值:Ordering[B]”。这是一个具体的 REPL 示例(Scala 2.8),其中 A = Score 和 B = CommentedScore:

class Score(val value: Double) extends Ordered[Score] {
  def compare(that: Score) = value.compare(that.value)
}
defined class Score

trait Comment { def comment: String }
defined trait Comment

class CommentedScore(value: Double, val comment: String) extends Score(value) with Comment
defined class CommentedScore

val s = new CommentedScore(10,"great")
s: CommentedScore = CommentedScore@842f23

val t = new CommentedScore(0,"mediocre")
t: CommentedScore = CommentedScore@dc2bbe

val commentedScores = Array(s,t)
commentedScores: Array[CommentedScore] = Array(CommentedScore@b3f01d, CommentedScore@4f3c89)

util.Sorting.quickSort(commentedScores)
error: could not find implicit value for parameter ord: Ordering[CommentedScore]
       util.Sorting.quickSort(commentedScores)
                             ^

我如何解决这个问题(也就是说,“免费”对 Array[B] = Array[CommentedScore] 进行排序,因为我知道如何对 Array[A] = Array[Score] 进行排序),以一种避免样板的优雅方式?

谢谢!

最佳答案

自己添加所需的隐式:

implicit val csOrd: Ordering[CommentedScore] = Ordering.by(_.value)

您可以将其放在 CommentedScore 伴随对象中,以便在使用站点上没有样板。

编辑:如果只想在继承树的顶部定义排序方法,仍然需要为每个子类提供一个Ordering,但是你可以根据compare对象中的一个来定义OrderingScore方法. IE。
object Score {
  implicit val ord: Ordering[Score] = Ordering.by(_.value)
}

object CommentedScore {
  implicit val csOrd = new Ordering[CommentedScore] {
    def compare(x: CommentedScore, y: CommentedScore) = Score.ord.compare(x, y)
  }
}

如果您不想为每个子类重新定义它,您可以使用通用方法来生成 Ordering :
object Score {
  implicit def ord[T <: Score]: Ordering[T] = Ordering.by(_.value)
}

这有点低效率,因为它是 def 而不是 val ,每次需要时它都会创建一个新的 Ordering 。然而,开销可能很小。另请注意,现在我们有 Ordered s,不需要 compare trait 和 Ordering 方法。

关于scala - 当 A 扩展 Ordered[A] 时,为子类 B < A 对 Array[B] 进行排序的优雅方式?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12171138/

10-11 18:53