【发布时间】:2021-03-18 21:18:38
【问题描述】:
来自List[+T],我了解到狗的列表也是与直觉完全一致的动物列表。从def :: [B >: A](elem: B): List[B] 我知道我可以将动物(B,不太具体)添加到狗列表(A,更具体),并会返回动物列表。这也符合直觉。所以基本上List 是好的。
来自Array[T] 我了解一组狗不是(不能用来代替a)一组动物,这是相当违反直觉的。一组狗确实也是一组动物,但显然 Scala 不同意。
我希望有人能直观地解释为什么 Array 保持不变,最好是用狗(或猫)来解释。
有Why are Arrays invariant, but Lists covariant?,但我正在寻找一个不(大量)涉及类型系统的更直观的解释。
【问题讨论】:
-
我自己的预感是“一个
Array的狗确实是一个Array在动物身上”可能并不适用于所有情况,特别是当它不用于只读位置但我不能直观地说出来。 -
AFAIK 原因几乎是历史性的——当 Java 引入带有协变数组的泛型时,人们意识到它们可能会爆炸(记住,它们是可变的)。例如。您可以简单地获取一个苹果数组,将其分配给 Array[Fruit] 类型的变量,然后将香蕉放入其中。这在运行时抛出。这就是为什么像数组这样的可变东西最好保持不变,而像 scala List 这样的不可变集合可以(并且确实有用)是协变的。
-
@slouc: "当 Java 引入带有协变数组的泛型时,人们意识到它们可能会爆炸" – 1) Java 中的协变数组独立于泛型而被破坏。它们早在 Java 1 中就已经被破坏了Java 5 中的泛型。 2) 关于安全协变和逆变的规则早在 Java 引入协变数组之前就已为人所知。如果人们在 Java 引入它们时才意识到它们可能会爆炸,那么他们要么无知,要么愚蠢。如果你看看那些设计 Java 的人的名字,很明显他们都不是那些东西,而是他们创造了一个……
-
...为了程序员的方便而牺牲安全性的设计决策,知道完全协变数组是不安全的。
标签: arrays scala scala-collections invariance