我正在使用现有的java库练习scala。将 Array [T] 传递给 func(Array [U]),其中 T<:U 是很常见的。例如:
爪哇:
public class Quick { ...
public static void sort(Comparable[] a) { ... }
}
public class Edge implements Comparable<Edge> { ... }
public class EdgeWeightedGraph { ...
public Iterable<Edge> edges() { ... }
}
Scala的:
class Kruskal(private val G: EdgeWeightedGraph) {
init()
private def init() = {
val es = G.edges().asScala.toArray
/* **Error** Type mismatch,
* expected: Array[Comparable[_]],
* actual: Array[Edge]
*/
Quick.sort(es)
...
}
}
我相信这是因为数组是不变的。这是我试图绕过这一点,但它看起来很丑陋而且效率低下:
val es = G.edges().asScala.map(_.asInstanceOf[Comparable[_]]).toArray)
Quick.sort(es)
我该如何以更好的方式做到这一点?
答案 0 :(得分:2)
数组是不变的,因为它们是可变的。如果它们不是不变的,你可以做类似
的事情class Fruit
class Apple extends Fruit
class Orange extends Fruit
val apples:Array[Apple] = Array(new Apple())
val fruits:Array[Fruit] = apples
fruits.update(0,new Orange)
val apple:Apple = apples(0) //<= epic fail I now have an orange as an apple ?
我能想到的唯一方法是将集合复制到等效的不可变集合(collection.immutable.Seq的子类型)
class Fruit
class Apple extends Fruit
class Orange extends Fruit
val apples:Array[Apple] = Array(new Apple())
val fruits:collection.immutable.Seq[Fruit]=apples.toList // or apples.toIndexedSeq
然后得到一个不可变的集合,你可以得到方差
在您的具体示例中,您可以更改
val es = G.edges().asScala.toArray
到
val es = G.edges().asScala.toIndexedSeq
但是你必须让QuickSort签名接受我猜的IndexedSeq。没有更多的代码就很难说清楚后果......