Why are Arrays invariant, but Lists covariant?

前端 未结 4 2030
被撕碎了的回忆
被撕碎了的回忆 2020-11-29 23:53

E.g. why does

val list:List[Any] = List[Int](1,2,3)

work, but

val arr:Array[Any] = Array[Int](1,2,3)

fail

4条回答
  •  陌清茗
    陌清茗 (楼主)
    2020-11-30 00:28

    The difference is that Lists are immutable while Arrays are mutable.

    To understand why mutability determines variance, consider making a mutable version of List - let's call it MutableList. We'll also make use of some example types: a base class Animal and 2 subclasses named Cat and Dog.

    trait Animal {
      def makeSound: String
    }
    
    class Cat extends Animal {
      def makeSound = "meow"
      def jump = // ...
    }
    
    class Dog extends Animal {
      def makeSound = "bark"
    }
    

    Notice that Cat has one more method (jump) than Dog.

    Then, define a function that accepts a mutable list of animals and modifies the list:

    def mindlessFunc(xs: MutableList[Animal]) = {
      xs += new Dog()
    }
    

    Now, horrible things will happen if you pass a list of cats into the function:

    val cats = MutableList[Cat](cat1, cat2)
    val horror = mindlessFunc(cats)
    

    If we were using a careless programming language, this will be ignored during compilation. Nevertheless, our world will not collapse if we only access the list of cats using the following code:

    cats.foreach(c => c.makeSound)
    

    But if we do this:

    cats.foreach(c => c.jump)
    

    A runtime error will occur. With Scala, writing such code is prevented, because the compiler will complain.

提交回复
热议问题