Liskov 替换原则如何应用于函数 return 类型?

How does the Liskov Substitution Principle apply to function return types?

里氏替换原则指出:

Objects in a program should be replaceable with instances of their sub-types without altering the correctness of that program.

假设:

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应用于输入参数时,应应用最低级别的抽象:

DO

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

不要

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

但是,LSP 是否适用于函数 return 类型,如果适用,反过来是否适用?

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

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

是的,是的。为了符合 LSP,重写方法中的参数类型必须是 contravariant,正如您所指出的。 return 类型的情况正好相反——这必须是 协变 ,即与 return 类型相同或更具体的类型方法被覆盖。

想想口号 "demand no more, promise no less." 让我们假设超类方法 return 是一个 Rectangle。这个方法可以被覆盖到 return 一个正方形,就像这样 "promises more," 但不能覆盖到 return 一个形状,就像这样 "promise less."