斯卡拉 – 如何规避不变性?例如.将Array [T]传递给func(Array [U]),其中T <:U

我正在使用现有的
java库练习scala.将Array [T]传递给func(Array [U])是很常见的,其中T <:U.例如:
Java的:

public class Quick { ...
    public static void sort(Comparable[] a) { ... }
}

public class Edge implements Comparable<Edge> { ... }

public class EdgeWeightedGraph { ...
    public Iterable<Edge> edges() { ... }
}

斯卡拉:

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)  
        ...
    }
}

我相信这是因为Array是不变的.这是我试图绕过这一点,但它看起来很丑陋和低效:

val es = G.edges().asScala.map(_.asInstanceOf[Comparable[_]]).toArray)
Quick.sort(es)

我该如何以更好的方式做到这一点?

最佳答案 数组是不变的,因为它们是可变的.如果它们不是不变的,你可以做类似的事情

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.没有更多代码就很难说出后果……

点赞