Liskov替代原理如何应用于函数返回类型?

时间:2019-05-09 11:11:54

标签: solid-principles liskov-substitution-principle

利斯科夫换人原则指出:

  

程序中的对象应该可以用其子类型的实例替换,而不会改变程序的正确性。

假设:

interface Iterable<T> {
    fun getIterator(): Iterator<T>
}

interface Collection<T> : Iterable<T> {
    val size: Int
}

interface List<T> : Collection<T> {
    fun get(index: Int): T
}

interface MutableList<T> : List<T> {
    fun set(index: Int, item: T): Unit
}

将LSP应用于输入参数时,应应用最低级别的抽象:

要做

fun foo(items: Iterable<Any>) { ... }

不要

fun foo(items: List<Any>) { ... }

但是,LSP是否适用于函数返回类型,如果适用,则反向适用吗?

fun bar(): Iterable<Any> { ... }

OR

fun bar(): List<Any> { ... }

1 个答案:

答案 0 :(得分:1)

是和是。如您所指出的,为了符合LSP,覆盖方法中的参数类型必须为 contravariant 。对于返回类型来说,情况恰恰相反-它必须是协变量,即与被重写的方法中的返回类型相同,或者是更特定的类型。

想到这样的口号:“不再要求,不再承诺”。假设超类方法返回一个Rectangle。可以忽略此方法以返回Square,因为它“承诺更多”,但不能返回Shape,因为这会“承诺更少”。