Kotlin проекционная избыточность

Читая о дисперсии и проекции дженериков Kotlin, я придумал совершенно незнакомую для меня концепцию. Может кто-нибудь объяснить, пожалуйста, что идея хочет объяснить автор? Пожалуйста, эту цитату из Kotlin в действии, MEAP:

Нет смысла получать out проекция параметра типа, который уже имеет out Дисперсия, такая как List<out T>, Это будет означать так же, как List<T>, так как List объявлен как class List<out T>, Компилятор Kotlin предупредит, что такая проекция избыточна.

Здесь есть два конкретных вопроса:

  1. Почему вам когда-нибудь нужно добавить проекцию в уже спроектированный список List?
  2. Даже если вы это сделаете, как вы получите тот же список?

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

  1. Почему вам когда-нибудь нужно добавить проекцию в уже спроектированный список List?

Нет, но это может произойти случайно, например, в результате рефакторинга или в глубокой цепочке вызовов, когда вы теряете из виду общие параметры, передаваемые вокруг.

  1. Даже если вы это сделаете, как вы получите тот же список?

По аналогии вы можете рассматривать проекцию как идемпотентное преобразование: out out T так же, как просто out T,

Другие вопросы по тегам