订购的参数化方法?

时间:2011-05-31 13:12:41

标签: scala variance type-parameter

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

我哪里错了?

2 个答案:

答案 0 :(得分:7)

首先,Ordering类似于Comparator,而不是Comparable。相当于Comparable的Scala是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不会扩展{{1} (或其他任何东西,因为它不是一个类)。

Scala有一个解决方法 - 从某些类到Comparable类的隐式转换。但是,要使用它,您需要使用view bound,这将使代码看起来像这样:

Ordered

请参阅def myMethod[A <% Ordered[A]](values: Seq[A]): Seq[A] = { // ... val sorted = values.sorted // } 而不是<%?这就是观点。

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

答案 1 :(得分: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]