【问题标题】:Liskov Substitution Principle and Arrays invarianceLiskov 替换原则和数组不变性
【发布时间】:2013-04-12 04:54:01
【问题描述】:

Liskov 替换原则告诉我们,如果 A 是 B 的子类型,那么我们可以用类型 B 做的所有事情都应该能够用类型 A 做。

因此,为了进一步调查,我创建了以下内容:

class Animal

class Dog extends Animal

class BlueDog extends Dog

我明白为什么我不允许这样做

val c: Array[Animal] = a

因为数组在 Scala 中不是协变的(就像在 Java 中一样)。

但是,我想我应该可以做到:

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

我希望 val b 没问题。 但我明白了:

class Array is invariant in type T. You may wish to investigate a wildcard type such as `_ >: ...

【问题讨论】:

  • 顺便问一下,为什么你认为val b: Array[BlueDog] = a 是健全的?即使数组不是一成不变的,您也将最不具体的分配给最具体的。如果您从 b 中获取元素并调用仅在 BlueDog 上定义的方法,您期望发生什么?

标签: scala covariant


【解决方案1】:
val a: Array[Dog] = Array(new Dog())
val b: Array[BlueDog] = a

有点奇怪,因为你的 BlueDog 比 Dog 更严格,可能还有其他方法。

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

那么下面的代码应该怎么做呢?

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

好吧,您的 Dog in Array a 没有 wolf() 方法....所以很明显,您不应该将父类型分配给子类型。

这就是以下工作的原因:

val dog: Dog = new BlueDog

但以下不是:

val blueDog: BlueDog = new Dog

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-05
    • 2010-12-03
    • 2019-10-29
    • 2016-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多