将通用通配符从Java转换为Scala

Nat*_*tix 6 java generics scala

java.util.Collections类中,我们有两个sort方法的变体,一个采用相应的任意对象列表Comparator:

public static <T> void sort(List<T> list, Comparator<? super T> comparator)
Run Code Online (Sandbox Code Playgroud)

并且需要一个Comparable对象列表:

public static <T extends Comparable<? super T>> void sort(List<T> list)
Run Code Online (Sandbox Code Playgroud)

我在想如何用有界通配符将这种方法签名翻译成Scala.对于第一个版本,我从字面上翻译了签名,一眼就没有编译问题:

def sort[T](list: List[T], comparator: Comparator[_ >: T]) { ??? }
Run Code Online (Sandbox Code Playgroud)

但后来我发现我无法使用以下参数调用此方法:

val comparator = new Comparator[Object] {
    def compare(o1: Object, o2: Object) = ???
}
val list = new ArrayList[Number]
sort[Object](list, comparator)
Run Code Online (Sandbox Code Playgroud)

最后一行给出了这个编译错误,即使我明确指定类型TObject.

类型不匹配; found:java.util.ArrayList [Number] required:java.util.List [Object]注意:Number <:Object,但Java定义的特征List在类型E中是不变的.您可能希望调查通配符类型,例如_ <: Object.(SLS 3.2.10)

实际上,我发现甚至不可能直接调用唯一的Java方法,因为它失败并且具有相同类型的错误.

Collections.sort[Object](list, comparator)
Run Code Online (Sandbox Code Playgroud)

至于具有可比列表的版本,我想出了这个声明:

def sort[T <: Comparable[_ >: T]](list: List[T]) { ??? }
Run Code Online (Sandbox Code Playgroud)

但这根本不起作用:

涉及T类的非法循环引用


我究竟做错了什么?Scala变体泛型是否遵循Java规则的不同规则?如何在Collections.sort没有实际编译错误的情况下调用该方法?

边注:

不,我真的不知道如何在Scala中对列表进行排序.我知道Scala有自己的集合,排序函数和比较对象(例如OrderedOrdering特征)的不同方法.我的问题涉及泛型方法的一般问题以及从Java到Scala的泛型的翻译.

gzm*_*zm0 5

您给出了错误的类型参数T:您对 a 进行排序List[Number],而不是 a List[Object]

sort[Number](list, comparator)
Run Code Online (Sandbox Code Playgroud)

将工作。

如果要在没有类型参数的情况下调用 sort,则需要定义两个参数列表(因为 Scala 中类型推断的工作方式):

def sort[T](list: List[T])(comparator: Comparator[_ >: T]) { ??? }

// Then
sort(list)(comparator)
Run Code Online (Sandbox Code Playgroud)

您可能需要考虑使用对协方差有适当支持的 Scala 类型(即在 Scala 中 aList[Number]是 a List[Object])。

对于具有可比版本的版本,您必须显式编写通配符:

def sort[T <: Comparable[T], U <: T](list: List[U]) { ??? }
Run Code Online (Sandbox Code Playgroud)