Конструкция объявления Koltin Generic-site <a T>

Я читал о причинах, почему у kotlin нет подстановочных знаков ( https://kotlinlang.org/docs/reference/generics.htm l). Все это привело к различию в декларации. У нас есть <in T> и <out T> конструкции, которые должны заменять подстановочные знаки. Я думаю, я понял, как работает <out T> но у меня проблемы с <in T> .
Поэтому в java мы могли бы написать что-то вроде этого:

 public List<? extends Number> list1; public List<? super String> list2; 

Первый случай после инициализации становится только списком для чтения (хотя это не совсем непреложная причина, мы можем его очистить), который можно было бы прочитать, если рассматривать каждый элемент как Number.
Второй случай – писать только (хотя мы могли бы его прочитать, если рассматривать каждый элемент как Object). Мы могли бы написать там String и подклассы.
В Kotlin мне удалось воссоздать пример list1, используя <out T> следующим образом:

 class Service { val container = Container(mutableListOf("1", "2", "3")) } class Container<T>(var list1: MutableList<out T>) 

Наконец, я попробовал что-то похожее на <in T> думая, что могу воссоздать пример list2, но я потерпел неудачу: введите описание изображения здесь

Может ли кто-нибудь объяснить мне, как достичь моего примера list2 в Котлине? Как я должен правильно использовать конструкцию <in T> ?

List<E> Kotlin List<E> не эквивалентен List<E> Java List<E> . Список Java имеет мутирующие функции, а список Kotlin доступен только для чтения. Это Kotlin MutableList<E> что эквивалентно списку Java.

Затем рассмотрим объявление List<E> : его параметр type является ковариантным ( out E ), а дисперсия объявления-сайта не может быть переопределена дисперсией на сайте-сайте, поэтому вы не можете иметь List<in T> .

Кроме того, разброс объявления-сайта out E означает, что E никогда не появляется во встроенном (нет функционального параметра типа E и не изменяемого свойства типа E ), и действительно, поскольку List<E> доступен только для чтения, он не принимает E в любую из своих функций (*) .

Вы можете преобразовать свой пример, чтобы вместо этого использовать MutableList<E> :

 class Container2<T>(var list2: MutableList<in T>) 

Интерфейс MutableList<E> имеет свой E инвариант, а in -projection на сайте использования не противоречит дисперсии объявления-сайта.

(*) Собственно, это так , но только с использованием параметров, отмеченных аннотацией @UnsafeVariance , которая просто подавляет конфликт дисперсии, более подробно об этом можно найти здесь .


Кроме того, небольшое замечание:

Все это привело к различию в декларации. У нас есть <in T> и <out T> конструкции, которые должны заменять подстановочные знаки.

На самом деле это вариация использования сайта, которая заменяет шаблоны Java. Отклонение на уровне объявления применяется только в объявлении параметра типа (где задан тип), и когда это так, все виды использования этого типа будут иметь эту дисперсию (например, когда вы используете List<CharSequence> , это фактически List<out CharSequence> из-за дисперсии объявления-сайта List<out E> ). И дисперсия использования-места, соответственно, для конкретных применений родового типа.