Kotlin проекционная избыточность
Читая о дисперсии и проекции дженериков Kotlin, я придумал совершенно незнакомую для меня концепцию. Может кто-нибудь объяснить, пожалуйста, что идея хочет объяснить автор? Пожалуйста, эту цитату из Kotlin в действии, MEAP:
Нет смысла получатьout
проекция параметра типа, который уже имеетout
Дисперсия, такая какList<out T>
, Это будет означать так же, какList<T>
, так какList
объявлен какclass List<out T>
, Компилятор Kotlin предупредит, что такая проекция избыточна.
Здесь есть два конкретных вопроса:
- Почему вам когда-нибудь нужно добавить проекцию в уже спроектированный список List?
- Даже если вы это сделаете, как вы получите тот же список?
2 ответа
Как указано, это будет "излишним", поэтому вы никогда не захотите этого делать. Это просто не добавляет никакой пользы. Вся цитата связана с дисперсией сайта использования, т. Е. Дисперсией, указанной клиентом (соответствует шаблонам в Java). Класс List<out T>
уже есть модификатор объявления сайта out
, что делает использование сайта-приложения out
излишний.
Вот пример избыточной дисперсии клиент-сайт:
fun <T> useList(list: List<out T>) {
println("first element: ${list[0]}")
}
Я применил out
модификатор параметра функции типа List<T>
Это пример использования сайта. Это избыточно, что компилятор замечает: "Projection is redundant"
, Это не делает это ни хуже, ни лучше.
С другой стороны, если вы используете тип, который еще не спроектирован на сайте объявлений, это имеет смысл. Например, Array
класс не ограничен в своей дисперсии: public class Array<T>
,
Переписать первый пример для использования Array
, вдруг имеет смысл добавить out
модификатор, так как параметр используется только как производитель T
т.е. не в in
позиция.
Пример значимой разницы между клиентом и сайтом:
fun <T> useArray(arr: Array<out T>) {
println("first element: ${arr[0]}")
}
Практическое правило
Как правило, соответствует Java PECS (Producer extends
Потребитель super
), вы можете запомнить POCI для Kotlin (Производитель out
Потребитель in
).
- Почему вам когда-нибудь нужно добавить проекцию в уже спроектированный список List?
Нет, но это может произойти случайно, например, в результате рефакторинга или в глубокой цепочке вызовов, когда вы теряете из виду общие параметры, передаваемые вокруг.
- Даже если вы это сделаете, как вы получите тот же список?
По аналогии вы можете рассматривать проекцию как идемпотентное преобразование: out out T
так же, как просто out T
,