0

The Liskov Substitution Principle tells us that if A is a subtype of B than everything we can do with type B we should be able to do with type A.

So to investigate this further, I create the following:

class Animal

class Dog extends Animal

class BlueDog extends Dog

I understand why I am not allowed to do

val c: Array[Animal] = a

as Arrays are not covariant in Scala (like they are in Java).

But, I think I should be able to do:

  val a: Array[Dog] = Array(new Dog())
  val b: Array[BlueDog] = a

I would expect val b to be ok. But I get:

class Array is invariant in type T. You may wish to investigate a wildcard type such as `_ >: ...
om-nom-nom
  • 62,329
  • 13
  • 183
  • 228
More Than Five
  • 9,959
  • 21
  • 77
  • 127
  • 3
    possible duplicate of [Scala: Why are Arrays invariant, but Lists covariant?](http://stackoverflow.com/questions/6684493/scala-why-are-arrays-invariant-but-lists-covariant) – om-nom-nom Apr 18 '13 at 21:53
  • 5
    By the way, why do you expect `val b: Array[BlueDog] = a` to be *sound*? Even if Arrays were not invariant, you are assigning least specific to the most specific. What you expect to happen if you take element from b and call method defined only on BlueDog? – om-nom-nom Apr 18 '13 at 22:00

1 Answers1

1
val a: Array[Dog] = Array(new Dog())
val b: Array[BlueDog] = a

Is a little strange, since your BlueDog is more strictly then Dog and may have other method.

class Animal
class Dog extends Animal
class BlueDog extends Dog {
  def wolf() { println ("I'm a blue dog") }
}

Then what should the following code do?

val a: Array[Dog] = new Array(new Dog())
val b: Array[BlueDog] = a
b(0).wolf()

Well, your Dog in Array a does not have wolf() method....so it's clearly that you should not assign a parent type to subtype.

That's why the following works:

val dog: Dog = new BlueDog

But the following doesn't:

val blueDog: BlueDog = new Dog
Joe Kearney
  • 7,397
  • 6
  • 34
  • 45
Brian Hsu
  • 8,781
  • 3
  • 47
  • 59