Назад к вопросам
Junior
85
questionbank
Какие виды дженериков вы знаете?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
Инвариантные, ковариантные и контравариантные.
- Инвариантность: Тип
List<A>не является подтипомList<B>и наоборот, даже еслиAявляется подтипомB. Тип сохраняется точно. - Ковариантность (out): Позволяет использовать подтипы.
List<A>является подтипомList<B>, еслиAявляется подтипомB. Используется для выходных параметров (возвращаемых значений).
fun foo(list: List<out Number>) {
// Можно читать из списка (Number, Double, Int и т.д.)
val number: Number = list[0]
// Нельзя добавлять в список (неизвестно, какого типа элементы ожидаются)
// list.add(1) // Ошибка компиляции
}
- Контравариантность (in): Позволяет использовать супертипы.
List<B>является подтипомList<A>, еслиAявляется подтипомB. Используется для входных параметров (аргументов).
fun foo(comparable: Comparable<in String>) {
// Можно передавать аргументы String (или его супертипы)
val result = comparable.compareTo("hello")
// Нельзя получать результаты типа String (неизвестно, какого типа результат)
// val str: String = comparable.compareTo("world") // Ошибка компиляции
}
В Kotlin эти концепции реализуются с помощью аннотаций out и in на параметрах типов. В Java используется wildcards (? extends для ковариантности и ? super для контравариантности).
| Тип | Назначение | Ключевое слово (Kotlin) | Wildcard (Java) | Разрешено чтение | Разрешена запись |
|---|---|---|---|---|---|
| Инвариантный | Точное совпадение типа | Нет | Нет | Да | Да |
| Ковариантный | Использование подтипов (producer - "out") | out |
? extends T |
Да | Нет |
| Контравариантный | Использование супертипов (consumer - "in") | in |
? super T |
Нет | Да |