【问题标题】:Parameterized method with Ordering?带排序的参数化方法?
【发布时间】:2011-05-31 13:12:41
【问题描述】:

现在我很困惑。我对 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 开始

我哪里错了?

【问题讨论】:

  • 应该是A <:> Ordering[A],A是Ordering[A]的子类型(即扩展)。这样它应该可以编译。

标签: scala variance type-parameter


【解决方案1】:

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

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

看到&lt;% 而不是&lt;:?这就是视图绑定。

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

【讨论】:

    【解决方案2】:

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

    scala> def myMethod[A : Ordering](values: Seq[A]): Seq[A] = values.sorted
    myMethod: [A](values: Seq[A])(implicit evidence$1: Ordering[A])Seq[A]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-29
      • 1970-01-01
      • 2014-02-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多