原因很简单。是因为Array
是一个可变集合。请记住,关于方差有一个非常简单的经验法则。
如果它产生一些东西,它可以是协变的。
如果它消耗一些东西,它可以是逆变的。
这就是为什么输入Functions
是逆变的,输出是协变的。
因为Arrays
是可变的,它们实际上既是生产者又是消费者,所以它们必须是不变的。
让我用一个简单的例子来说明为什么它必须是这样的。
// Assume this compiles, it doesn't.
final class CovariantArray[+A] (arr: Array[A]) {
def length: Int = arr.length
def apply(i: Int): A = arr(i)
def update(i: Int, a: A): Unit = {
arr(i) = a
}
}
sealed trait Pet
final case class Dog(name: String) extends Pet
final case class Cat(name: String) extends Pet
val myDogs: CovariantArray[Dog] = CovariantArray(Dog("Luna"), Dog("Lucas"))
val myPets: CovariantArray[Pet] = myDogs // Valid due covariance.
val myCat: Cat = Cat("Milton")
myPets(1) = myCat // Valid because Liskov.
val myDog: Dog = myDogs(1) // Runtime error Cat is not Dog.
您可以使用 normal在Java中重现此错误Arrays
,Scala根本不会让您编译。