0Pricing
Kotlin Academy · Урок

Индексация и вызов

get, set и invoke

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

Оператор индекса

Определение operator fun get позволяет читать значения с помощью синтаксиса квадратных скобок: obj[i].

class Row(val cells: List<String>) {
    operator fun get(i: Int) = cells[i]
}

fun main() {
    val r = Row(listOf("a", "b", "c"))
    println(r[1])
}

Запись с помощью set

operator fun set позволяет присваивать значения: obj[i] = value. Последний параметр — это значение.

class Grid {
    private val data = IntArray(3)
    operator fun get(i: Int) = data[i]
    operator fun set(i: Int, value: Int) { data[i] = value }
}

fun main() {
    val g = Grid()
    g[0] = 42
    println(g[0])
}

Индексация по нескольким аргументам

get и set могут принимать несколько индексов, что особенно удобно для матриц.

class Matrix {
    private val d = Array(2) { IntArray(2) }
    operator fun get(r: Int, c: Int) = d[r][c]
    operator fun set(r: Int, c: Int, v: Int) { d[r][c] = v }
}

fun main() {
    val m = Matrix()
    m[1, 1] = 9
    println(m[1, 1])
}

Индексация ключами не типа Int

Параметры индекса могут иметь любой тип, что позволяет обращаться к данным подобно карте.

class Settings {
    private val map = mutableMapOf<String, String>()
    operator fun get(key: String) = map[key]
    operator fun set(key: String, value: String) { map[key] = value }
}

fun main() {
    val s = Settings()
    s["theme"] = "dark"
    println(s["theme"])
}

Оператор invoke

Определение operator fun invoke позволяет вызывать экземпляр как функцию: obj().

class Greeter(val name: String) {
    operator fun invoke() = "Hello, $name"
}

fun main() {
    val g = Greeter("Sam")
    println(g())
}

Вызов invoke с аргументами

invoke может принимать параметры, благодаря чему объект ведёт себя как функция с параметрами.

class Multiplier(val factor: Int) {
    operator fun invoke(x: Int) = x * factor
}

fun main() {
    val triple = Multiplier(3)
    println(triple(5))
}

Вызываемые объекты с состоянием

Поскольку объект хранит состояние, invoke позволяет создавать настраиваемые объекты, подобные функциям.

class Accumulator {
    var total = 0
    operator fun invoke(n: Int) { total += n }
}

fun main() {
    val acc = Accumulator()
    acc(5)
    acc(10)
    println(acc.total)
}

Несколько перегрузок вызова

Можно объявить несколько перегрузок invoke с разными параметрами.

class Printer {
    operator fun invoke(s: String) = println(s)
    operator fun invoke(n: Int) = println("num: $n")
}

fun main() {
    val p = Printer()
    p("hi")
    p(7)
}

Индекс в выражениях

Доступ по индексу естественно сочетается с другими операциями.

class Scores(private val list: List<Int>) {
    operator fun get(i: Int) = list[i]
}

fun main() {
    val s = Scores(listOf(10, 20, 30))
    println(s[0] + s[2])
}

Объединение доступа и вызова

Тип может поддерживать как индексацию, так и вызов, обеспечивая выразительный программный интерфейс.

class Lookup(private val data: Map<String, Int>) {
    operator fun get(key: String) = data[key]
    operator fun invoke() = data.size
}

fun main() {
    val l = Lookup(mapOf("a" to 1))
    println(l["a"])
    println(l())
}

Как это используется в стандартной библиотеке

Операторы list[i] у списков и map[key] у отображений устроены именно так. Ваши типы тоже могут выглядеть столь же естественно.

fun main() {
    val list = listOf(1, 2, 3)
    val map = mapOf("x" to 9)
    println(list[0])
    println(map["x"])
}

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

Проверьте, насколько хорошо Вы поняли индексацию и вызов.

Итоги

Вы изучили индексацию и вызов:

  • get реализует доступ obj[i], а set — присваивание obj[i] = v.
  • Операторы индекса поддерживают несколько ключей и ключи не только типа Int.
  • invoke позволяет вызывать экземпляры как функции — с аргументами или без них.
  • В стандартных коллекциях используются именно эти операторы.
class Box {
    private val m = mutableMapOf<String, Int>()
    operator fun get(k: String) = m[k]
    operator fun set(k: String, v: Int) { m[k] = v }
}

fun main() {
    val b = Box()
    b["x"] = 5
    println(b["x"])
}

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

Урок «Индексация и вызов» бесплатный?

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

Чему я научусь в уроке «Индексация и вызов»?

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

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

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

Сколько времени занимает урок «Индексация и вызов»?

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

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

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

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

  1. Функции-операторы
  2. Операторы сравнения
  3. Индексация и вызов
  4. Лучшие практики
← Назад к Kotlin Academy