Ash*_*ary 3 arrays scala scala-collections invariance
据List[+T]我了解,狗的列表也是与直觉完全一致的动物列表。据def :: [B >: A](elem: B): List[B]我所知,我可以将动物(B,不太具体)添加到狗(A,更具体)列表中,并会取回动物列表。这也符合直觉。所以基本上List是好的。
据Array[T]我了解,一组狗不是(不能用来代替 a)一组相当违反直觉的动物。一组狗确实也是一组动物,但显然 Scala 不同意。
我希望有人能直观地解释为什么Array是不变的,最好是用狗(或猫)来解释。
还有为什么阵列不变,但名单协变?但我正在寻找一个更直观的解释,它不(大量)涉及类型系统。
Lui*_*rez 15
The reason is pretty simple. Is because Array is a mutable collection. Remember there is a very easy rule of thumb about variance.
If it produces something it can be covariant.
If it consumes something it can be contravariant.
That is why Functions are contravariant on input and covariant on output.
Because Arrays are mutable they are in fact both producers and consumers of something, so they have to be invariant.
Let me show why it has to be like that with a simple example.
// 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.
Run Code Online (Sandbox Code Playgroud)
You can reproduce this error in Java using normal Arrays, Scala will simply not let you compile.
| 归档时间: |
|
| 查看次数: |
124 次 |
| 最近记录: |