利斯科夫换人原则指出:
程序中的对象应该可以用其子类型的实例替换,而不会改变程序的正确性。
假设:
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> { ... }
答案 0 :(得分:1)
是和是。如您所指出的,为了符合LSP,覆盖方法中的参数类型必须为 contravariant 。对于返回类型来说,情况恰恰相反-它必须是协变量,即与被重写的方法中的返回类型相同,或者是更特定的类型。
想到这样的口号:“不再要求,不再承诺”。假设超类方法返回一个Rectangle。可以忽略此方法以返回Square,因为它“承诺更多”,但不能返回Shape,因为这会“承诺更少”。