Как принцип подстановки Лискова применяется к типам возвращаемых функций? - PullRequest
0 голосов
/ 09 мая 2019

Принцип замещения Лискова гласит:

Объекты в программе должны заменяться экземплярами их подтипов без изменения правильности этой программы.

Предполагая, что:

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>) { ... }

DO NOT

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

Но применяется ли LSP к типам возвращаемых функций, и если да, применяется ли обратное?

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

OR

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

1 Ответ

1 голос
/ 12 мая 2019

Да и да. Чтобы соответствовать LSP, типы аргументов в переопределяющем методе должны быть контравариантными , как вы указали. Обратное верно для возвращаемого типа - это должно быть ковариантно , то есть того же типа или более определенного типа, что и тип возвращаемого значения в методе, который переопределяется.

Подумайте о лозунге "не требуй больше, обещай не меньше". Допустим, метод суперкласса возвращает Rectangle. Этот метод может быть переопределен для возврата квадрата, поскольку это «обещает больше», но не для возврата формы, поскольку это «обещает меньше».

...