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."
里氏替换原则指出:
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."