0Pricing
Kotlin Academy · Урок

Ограничения обобщений

Ограничивайте параметры типов

«Ограничения обобщений» — бесплатный урок Kotlin Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Kotlin Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Kotlin Academy содержит 4 уроков всего.

Ограничения параметров типов

Иногда обобщённый тип должен принимать только определённые типы, например сравнимые типы или типы, являющиеся подклассами базового типа. Ограничения обобщённых типов задают верхнюю границу параметра типа.

Стандартная верхняя граница

Без ограничения верхняя граница параметра типа — Any?, поэтому он принимает любой тип, в том числе допускающий значение null. Чтобы разрешить только типы, не допускающие null, задайте для него границу Any.

fun <T : Any> requireNonNull(value: T): T {
    return value
}

fun main() {
    println(requireNonNull(42))
}

Одна верхняя граница

Используйте T : Bound, чтобы потребовать, чтобы T был подтипом Bound. Это позволяет вызывать члены Bound внутри функции.

fun <T : Number> sumDoubled(a: T, b: T): Double {
    return a.toDouble() * 2 + b.toDouble() * 2
}

fun main() {
    println(sumDoubled(3, 4))
    println(sumDoubled(1.5, 2.5))
}

Граница сравнимости

Распространённая граница — Comparable<T>: она позволяет сравнивать элементы с помощью <, > или compareTo.

fun <T : Comparable<T>> maxOf2(a: T, b: T): T {
    return if (a > b) a else b
}

fun main() {
    println(maxOf2(3, 9))
    println(maxOf2("apple", "banana"))
}

Вызов членов ограничивающего типа

Внутри обобщённого типа с ограничением компилятор знает, что T обладает возможностями ограничивающего типа, поэтому эти методы можно вызывать напрямую, без приведения типа.

fun <T : CharSequence> describe(value: T): String {
    return "Length is ${value.length}"
}

fun main() {
    println(describe("hello"))
    println(describe(StringBuilder("hi")))
}

Несколько границ с помощью условия where

Если границ больше одной, используйте предложение where. Тогда T должен удовлетворять ALL перечисленным ограничениям.

fun <T> copyWhenValid(value: T): T
    where T : CharSequence, T : Comparable<T> {
    return value
}

fun main() {
    println(copyWhenValid("text"))
}

Ограничения для классов

Ограничения работают и для обобщённых классов, определяя, с какими типами можно создавать экземпляры класса.

class NumberBox<T : Number>(val value: T) {
    fun asDouble(): Double = value.toDouble()
}

fun main() {
    val box = NumberBox(10)
    println(box.asDouble())
}

Операции, доступные благодаря ограничению

Главная цель ограничения — открыть доступ к операциям. Без T : Number нельзя было бы вызвать toDouble(); верхняя граница гарантирует наличие этого метода.

Ограничение на отсутствие null на практике

Ограничение типом Any отклоняет аргументы, допускающие null, ещё во время компиляции. Это удобный способ потребовать обобщённые типы без null.

fun <T : Any> firstNonNull(a: T, b: T): T = a

fun main() {
    println(firstNonNull("x", "y"))
    // firstNonNull(null, "y") would not compile
}

Сочетание с вариантностью

Ограничения и вариантность решают разные задачи: вариантность (in/out) управляет отношениями подтипов, а ограничения (границы : и where) определяют, какие типы разрешены. Их можно использовать вместе.

Проектирование хороших ограничений

Добавляйте ограничение только тогда, когда Вам нужны определённые возможности типа. Слишком строгие ограничения снижают повторное использование, а слишком слабые вынуждают применять приведения типов. Выбирайте наиболее общий тип, который предоставляет используемые Вами операции.

Быстрая проверка

Как потребовать, чтобы параметр типа удовлетворял нескольким границам?

Повторение

Ограничения обобщённых типов задают верхние границы с помощью T : Bound (или where для нескольких границ), открывая доступ к операциям ограничивающего типа и исключая несовместимые типы. Ограничение типом Any требует отсутствия null. В сочетании с вариантностью ограничения позволяют создавать безопасные и выразительные обобщённые типы. На этом курс «Обобщённые типы и вариантность» завершён.

Часто задаваемые вопросы

Урок «Ограничения обобщений» бесплатный?

Да — полный текст урока «Ограничения обобщений» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Kotlin Academy, подпишись на CoddyKit PRO. Курс Kotlin Academy содержит 4 уроков всего.

Чему я научусь в уроке «Ограничения обобщений»?

Ограничивайте параметры типов Ты практикуешь Kotlin Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Kotlin Academy?

Предыдущий опыт не требуется. Kotlin Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Ограничения обобщений»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Kotlin Academy?

Да. Каждый урок Kotlin Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Обобщённые функции и классы
  2. Вариативность на месте объявления
  3. Вариативность на месте использования
  4. Ограничения обобщений
← Назад к Kotlin Academy