3

现在我很困惑。我对 Scala 很陌生,已经使用了几个星期,我想我已经熟悉它了,但是我被困在下面这个看似微不足道的案例中。

我找不到与此 Java 声明等效的 Scala:

public static <T extends Comparable<T>> List<T> myMethod(List<T> values) {
  // ...
  final List<T> sorted = new ArrayList<T>(values);
  Collections.sort(sorted);
  // ...
}

我认为以下会做:

def myMethod[A >: Ordering[A]](values: Seq[A]): Seq[A] = {
  // ...
  val sorted = values.sorted
  //
}

但是,我收到以下错误:

错误:涉及类型 A 的非法循环引用

错误:类型 scala.math.Ordering[A] 的发散隐式扩展从对象排序中的方法 Tuple9 开始

我哪里错了?

4

2 回答 2

7

首先,Ordering是类似于Comparator,不是Comparable。Scala 等价于Comparable. Ordered接下来,extends等价的是<:,不是>:。后者相当于super-- T super COmparable<T>,这不是你想要的。因此,通过这两个修复程序,您的代码应如下所示:

def myMethod[A <: Ordered[A]](values: Seq[A]): Seq[A] = {
  // ...
  val sorted = values.sorted
  //
}

但是,这不适用于Seq[Int],例如,因为Int不扩展Ordered——就像 Java 的int不扩展Comparable(或其他任何东西,因为它不是一个类)。

Scala 有一个解决方法——从某些类到Ordered类的隐式转换。但是,要使用它,您需要使用view bound,这将使代码如下所示:

def myMethod[A <% Ordered[A]](values: Seq[A]): Seq[A] = {
  // ...
  val sorted = values.sorted
  //
}

看到<%而不是<:?这就是视图绑定。

现在,Scala 圈子中当前的偏好是使用上下文边界而不是视图边界,因为它们更灵活。这意味着Ordering以其他答案描述的方式使用 , 。

于 2011-05-31T18:01:23.053 回答
5

那应该是上下文绑定,如下所示。

scala> def myMethod[A : Ordering](values: Seq[A]): Seq[A] = values.sorted
myMethod: [A](values: Seq[A])(implicit evidence$1: Ordering[A])Seq[A]
于 2011-05-31T13:49:23.043 回答