【问题标题】:How to circumvent invariance? E.g. passing Array[T] to func(Array[U]) where T<:U如何规避不变性?例如。将 Array[T] 传递给 func(Array[U]) 其中 T<:U
【发布时间】:2013-12-19 09:51:16
【问题描述】:

我正在使用现有的 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)

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

【问题讨论】:

    标签: scala variance


    【解决方案1】:

    数组是不变的,因为它们是可变的。如果它们不是不变的,你可以做类似

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

    【讨论】:

    • 投票支持不变性。但是在库签名固定的情况下是不可行的,而且经常是这种情况。
    • 我猜你不能改变 Quick.sort 签名并且实现已经到位。如果不知道哪些部分是你的代码,哪些部分是库以及哪些库很难更有用。 ..
    猜你喜欢
    • 2014-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-30
    • 1970-01-01
    • 1970-01-01
    • 2012-10-15
    相关资源
    最近更新 更多