Обобщённые функции и ограничения типов с where
Пишите обобщённые функции с одним или несколькими ограничениями типов.
«Обобщённые функции и ограничения типов с where» — бесплатный урок Kotlin Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Kotlin Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Kotlin Academy содержит 4 уроков всего.
Основы обобщённых функций
Обобщённые функции используют параметры типа в угловых скобках перед именем функции. Параметр типа можно использовать в типах параметров и возвращаемых значениях.
fun <T> identity(value: T): T = value
fun <T> listOf2(a: T, b: T): List<T> = listOf(a, b)
fun main() {
println(identity(42)) // 42
println(identity("hello")) // hello
println(listOf2(1, 2)) // [1, 2]
}Верхние границы с ограничением «:»
Ограничьте параметр типа верхней границей с помощью :. Тип должен быть подтипом этой границы.
fun <T : Comparable<T>> max(a: T, b: T): T = if (a >= b) a else b
fun main() {
println(max(3, 7)) // 7
println(max("apple", "banana")) // banana
// max(listOf(1), listOf(2)) // error: List is not Comparable
}Обнуляемая верхняя граница
По умолчанию верхняя граница — Any? (допускающая пустое значение). Используйте T : Any, чтобы исключить пустое значение.
fun <T : Any> notNull(value: T?): T {
return value ?: throw IllegalArgumentException("Value is null")
}
fun main() {
println(notNull("hello")) // hello
try { notNull(null) } catch (e: Exception) { println(e.message) }
}Несколько ограничений с where
Используйте предложение where, чтобы применить несколько ограничений к одному параметру типа.
fun <T> process(item: T): String
where T : Comparable<T>, T : CharSequence {
return "Length=${item.length}, sorted=${item > "a"}"
}
fun main() {
println(process("kotlin")) // Length=6, sorted=true
// process(42) // error: Int doesn't implement CharSequence
}where в классе
Предложение where также работает с параметрами типа уровня класса.
class SortedContainer<T>(private val items: MutableList<T> = mutableListOf())
where T : Comparable<T>, T : Any {
fun add(item: T) { items.add(item); items.sort() }
fun top(): T? = items.lastOrNull()
}
fun main() {
val c = SortedContainer<Int>()
c.add(5); c.add(2); c.add(8)
println(c.top()) // 8
}Обобщённые функции-расширения
Функции-расширения также могут иметь параметры типа, благодаря чему их можно применять к определённым обобщённым типам.
fun <T : Comparable<T>> List<T>.second(): T? {
return if (size >= 2) this[1] else null
}
fun main() {
println(listOf(10, 20, 30).second()) // 20
println(listOf("a").second()) // null
}Параметр типа в возвращаемой позиции
Обобщённые функции могут вывести тип из контекста, избавляя от необходимости явно указывать аргументы типа в месте вызова.
fun <T> MutableList<T>.popOrDefault(default: T): T {
return if (isEmpty()) default else removeAt(lastIndex)
}
fun main() {
val list = mutableListOf(1, 2, 3)
println(list.popOrDefault(0)) // 3
println(list.popOrDefault(0)) // 2
println(mutableListOf<Int>().popOrDefault(-1)) // -1
}Повторно используемые обобщённые утилиты
Обобщённые функции позволяют повторно использовать вспомогательные функции для разных типов без дублирования.
fun <T> Iterable<T>.firstOrElse(default: T): T = firstOrNull() ?: default
fun <T, R : Comparable<R>> Iterable<T>.maxByOrElse(selector: (T) -> R, default: T): T =
maxByOrNull(selector) ?: default
fun main() {
println(listOf<String>().firstOrElse("fallback")) // fallback
println(listOf("a","bbb","cc").maxByOrElse({ it.length }, "")) // bbb
}Проекция со звёздочкой и ограниченный шаблон
Сравните использование ограниченного параметра типа (полезно, когда нужно создавать или принимать значения T) с проекцией со звёздочкой (когда тип неизвестен).
fun <T : Number> sumList(list: List<T>): Double =
list.sumOf { it.toDouble() }
// Star projection: read-only, type unknown
fun printAll(list: List<*>) = list.forEach { println(it) }
fun main() {
println(sumList(listOf(1, 2, 3))) // 6.0
printAll(listOf("a", 1, true)) // a, 1, true
}Обобщённая перестановка пары
Простая, но наглядная обобщённая функция, меняющая местами компоненты пары.
fun <A, B> Pair<A, B>.swap(): Pair<B, A> = Pair(second, first)
fun main() {
val pair = Pair("hello", 42)
val swapped = pair.swap()
println(swapped) // (42, hello)
}Практика: извлечение значения из обобщённого результата
Используйте ограниченные обобщённые типы, чтобы написать утилиту, применяющую типизированное преобразование к Result<T>.
fun <T : Any, R : Any> Result<T>.mapNotNull(transform: (T) -> R?): Result<R> {
return fold(
onSuccess = { v ->
val r = transform(v)
if (r != null) Result.success(r) else Result.failure(NoSuchElementException())
},
onFailure = { Result.failure(it) }
)
}
fun main() {
val r = Result.success("123")
val n = r.mapNotNull { it.toIntOrNull() }
println(n) // Success(123)
}Быстрая проверка
Как применить несколько ограничений к одному параметру типа?
Итоги
Обобщённые функции используют параметры типа для написания повторно используемого и типобезопасного кода. Используйте : для одной верхней границы или where для нескольких границ. Компилятор Kotlin проверяет ограничения в месте вызова.
Изучай Kotlin с ИИ-репетитором — бесплатно
Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.
- Курсы
- 51
- Уроки
- 203
Часто задаваемые вопросы
Урок «Обобщённые функции и ограничения типов с where» бесплатный?
Да — полный текст урока «Обобщённые функции и ограничения типов с where» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Kotlin Academy, подпишись на CoddyKit PRO. Курс Kotlin Academy содержит 4 уроков всего.
Чему я научусь в уроке «Обобщённые функции и ограничения типов с where»?
Пишите обобщённые функции с одним или несколькими ограничениями типов. Ты практикуешь Kotlin Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Kotlin Academy?
Предыдущий опыт не требуется. Kotlin Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Обобщённые функции и ограничения типов с where»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Kotlin Academy?
Да. Каждый урок Kotlin Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Обобщённые функции и ограничения типов с where
- Вариативность на месте объявления: in и out
- Звёздная проекция и случаи применения *
- Стирание типов и параметры типов reified