(←) предыдущая запись ; следующая запись (→)
Теперь представьте, что вы хотите собрать список всех произведений Set<Text>
и список всех поэтических текстов Set<Poem>
. В какой-то момент вам надоедает делать разные обработчики для двух разных списков и вы задаётесь вопросом, а нельзя ли и это место как-то унифицировать?
Кажется очевидным, что множество стихотворений является множеством текстов.
Но это не совсем так!
Подтип должен уметь делать всё то же самое, что умеет делать родительский тип (это называется «принцип подстановки Барбары Лисков»). Это ограничение позволяет использовать использовать подтип везде, где можно использовать надтип.
То есть, если у вас есть функция печати текста print_text(Text t)
, то и стихотворения она распечатывать тоже умеет. Такое применение вполне корректно: print_text(some_poem)
.
Если говорить точнее, принцип формулируется так: «Любое утверждение верное для родительского типа должно быть так же верно и для подтипа» (см. комментарий).
Из этого принципа есть важнейшее следствие: тип определяется не просто по данным, из которых он состоит, но и по действиям, которые с ним можно сделать.
Значит нам нужно выбрать действия, которые мы разрешаем делать с нашим контейнером Set<T>
. И от того, какие операции мы введём, будет зависеть и то, как связаны типы.
Скажем, что множество имеет две операции (знатокам джавы просьба не волноваться: это ненастоящий Set, ненастоящая Java и слова «множество» и «список» я использую взаимозаменяемо):
— T get()
— операция, которая выбирает какой-то объект из списка и возвращает его вам. Выданный вам объект имеет тип T
.
— put(T)
— операция, которая добавляет объект типа T
в список.
Давайте поймём, как при таком наборе действий соотносятся между собой множество текстов и множество стихотворений.
(2/4)