Назад к вопросам
Middle
132
questionbank
Как работать с обобщенными типами (generics) в Kotlin?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
Обобщенные типы в Kotlin позволяют создавать классы, интерфейсы и функции, работающие с данными разных типов, сохраняя при этом типобезопасность во время компиляции.
Основные понятия и способы работы:
- Объявление обобщенных классов и интерфейсов:
class Box<T>(val item: T) // Обобщенный класс с параметром типа T interface MyList<E> { // Обобщенный интерфейс с параметром типа E fun add(element: E) fun get(index: Int): E } - Объявление обобщенных функций:
fun <T> printAnything(value: T) { // Обобщенная функция с параметром типа T println(value) } - Создание экземпляров обобщенных типов:
val intBox: Box<Int> = Box(123) // Указание конкретного типа (Int) val stringBox = Box("hello") // Компилятор выводит тип (String) - Вариантность: Позволяет определить, как работают подтипы с обобщенными типами.
- Ковариантность (out): Позволяет использовать тип и его подтипы. Обозначается
out. Пример:List<out Any>может содержатьList<String>. Используется для типов, которые производят значения (например, чтение из коллекции).interface Producer<out T> { // out T - ковариантный параметр fun produce(): T } - Контравариантность (in): Позволяет использовать тип и его надтипы. Обозначается
in. Пример:Comparator<in String>может работать сComparator<Any>. Используется для типов, которые потребляют значения (например, запись в коллекцию).interface Consumer<in T> { // in T - контравариантный параметр fun consume(value: T) } - Инвариантность: Тип в обобщенном параметре должен быть точно таким же. Это поведение по умолчанию.
- Ковариантность (out): Позволяет использовать тип и его подтипы. Обозначается
- Ограничения типов (
where): Позволяет ограничить тип параметром, чтобы он реализовал определенные интерфейсы или наследовался от определенного класса.fun <T : Comparable<T>> max(a: T, b: T): T { // T должен реализовывать Comparable return if (a > b) a else b } fun <T> process(item: T) where T : Runnable, T : Comparable<T> { item.run() // ... используем сравнимость } - Звездная (star) проекция (
*): Используется, когда неважны конкретные аргументы типа. Аналогично<?>в Java.fun printList(list: List<*>) { // Можно принимать список любого типа for (item in list) { println(item) } }
Обобщенные типы в Kotlin используют стирание типов (type erasure), как и в Java. Информация о конкретных типах параметров теряется во время выполнения. Для работы с типами во время выполнения используются реифицированные (reified) типы.
- Реифицированные типы (
reified): Доступны только для inline функций. Позволяют сохранить информацию о типе параметра во время выполнения.inline fun <reified T> checkType(value: Any) { // T - реифицированный тип if (value is T) { println("Value is of type T") } else { println("Value is not of type T") } }