Spec-Zone.ru › Kotlin 2

Перегрузка операторов

Kotlin позволяет предоставлять собственные реализации для предопределённого набора операторов типов. Эти операторы имеют предопределённое символьное представление (например, + или *) и приоритет. Чтобы реализовать оператор, предоставьте функцию-член или функцию-расширение с определённым именем для соответствующего типа. Этот тип становится типом левого операнда для бинарных операций и типом аргумента для унарных.

Чтобы перегрузить оператор, пометьте соответствующую функцию модификатором operator:

interface IndexedContainer {
    operator fun get(index: Int)
}

При переопределении перегруженных операторов можно опустить operator:

class OrdersList: IndexedContainer {
    override fun get(index: Int) { /*...*/ }   
}

Унарные операции

Унарные префиксные операторы

Выражение

Переводится в

+a

a.unaryPlus()

-a

a.unaryMinus()

!a

a.not()

Эта таблица означает, что при обработке компилятором, например, выражения +a выполняются следующие шаги:

  • Определяется тип a; пусть это будет T.

  • Для получателя T ищется функция unaryPlus() с модификатором operator и без параметров, то есть функция-член или функция-расширение.

  • Если функция отсутствует или неоднозначна, возникает ошибка компиляции.

  • Если функция существует и её тип возвращаемого значения — R, выражение +a имеет тип R.

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

Например, вот как можно перегрузить унарный оператор минуса:

data class Point(val x: Int, val y: Int)

operator fun Point.unaryMinus() = Point(-x, -y)

val point = Point(10, 20)

fun main() {
   println(-point)  // prints "Point(x=-10, y=-20)"
}

Инкременты и декременты

Выражение

Переводится в

a++

a.inc() + см. ниже

a--

a.dec() + см. ниже

Функции inc() и dec() должны возвращать значение, которое будет присвоено переменной, к которой применена операция ++ или --. Они не должны изменять объект, к которому применена операция inc или dec.

Для разрешения оператора в постфиксной форме, например a++, компилятор выполняет следующие шаги:

  • Определяет тип a; пусть это будет T.

  • Ищет функцию inc() с модификатором operator и без параметров, применимую к получателю типа T.

  • Проверяет, что тип возвращаемого значения функции является подтипом T.

Вычисление выражения приводит к следующим действиям:

  • Сохраняется исходное значение a во временном хранилище a0.

  • Результат a0.inc() присваивается a.

  • a0 возвращается как результат выражения.

Для a-- шаги полностью аналогичны.

Для префиксных форм ++a и --a разрешение выполняется аналогичным образом, а результатом будет следующее:

  • Результат a.inc() присваивается a.

  • Новое значение a возвращается как результат выражения.

Бинарные операции

Арифметические операторы

Выражение

Переводится в

a + b

a.plus(b)

a - b

a.minus(b)

a * b

a.times(b)

a / b

a.div(b)

a % b

a.rem(b)

a..b

a.rangeTo(b)

a..<b

a.rangeUntil(b)

Для операций из этой таблицы компилятор просто разрешает выражение, указанное в столбце «Переводится в».

Ниже приведён пример класса Counter, который начинается с заданного значения и может увеличиваться с помощью перегруженного оператора +:

data class Counter(val dayIndex: Int) {
    operator fun plus(increment: Int): Counter {
        return Counter(dayIndex + increment)
    }
}

Оператор in

Выражение

Переводится в

a in b

b.contains(a)

a !in b

!b.contains(a)

Для in и !in процедура аналогична, но порядок аргументов обратный.

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

Выражение

Переводится в

a[i]

a.get(i)

a[i, j]

a.get(i, j)

a[i_1, ..., i_n]

a.get(i_1, ..., i_n)

a[i] = b

a.set(i, b)

a[i, j] = b

a.set(i, j, b)

a[i_1, ..., i_n] = b

a.set(i_1, ..., i_n, b)

Квадратные скобки преобразуются в вызовы get и set с соответствующим количеством аргументов.

Оператор invoke

Выражение

Переводится в

a()

a.invoke()

a(i)

a.invoke(i)

a(i, j)

a.invoke(i, j)

a(i_1, ..., i_n)

a.invoke(i_1, ..., i_n)

Круглые скобки преобразуются в вызовы invoke с соответствующим количеством аргументов.

Составные операторы присваивания

Выражение

Переводится в

a += b

a.plusAssign(b)

a -= b

a.minusAssign(b)

a *= b

a.timesAssign(b)

a /= b

a.divAssign(b)

a %= b

a.remAssign(b)

Для операций присваивания, например a += b, компилятор выполняет следующие шаги:

  • Если доступна функция из правого столбца:

    • Если также доступна соответствующая бинарная функция (то есть plus() для plusAssign()), a является изменяемой переменной, а тип возвращаемого значения plus является подтипом типа a, сообщается об ошибке (неоднозначность).

    • Проверяет, что тип возвращаемого значения — Unit, иначе сообщает об ошибке.

    • Генерирует код для a.plusAssign(b).

  • В противном случае пытается сгенерировать код для a = a + b (включая проверку типов: тип a + b должен быть подтипом a).

В Kotlin присваивания не являются выражениями.

Операторы равенства и неравенства

Выражение

Переводится в

a == b

a?.equals(b) ?: (b === null)

a != b

!(a?.equals(b) ?: (b === null))

Эти операторы работают только с функцией equals(other: Any?): Boolean, которую можно переопределить, чтобы предоставить собственную реализацию проверки равенства. Любые другие функции с тем же именем (например, equals(other: Foo)) игнорируются.

Kotlin вызывает .equals(), если ни один из операндов напрямую не сравнивается с null в выражении == и сравнение выполняется не между двумя типами с плавающей точкой. В противном случае Kotlin использует === для прямых сравнений null и сравнивает ненулевые значения с плавающей точкой по их числовому значению.

Операторы === и !== (проверки идентичности) нельзя перегрузить, поэтому соглашения для них не предусмотрены.

Операторы сравнения

Выражение

Переводится в

a > b

a.compareTo(b) > 0

a < b

a.compareTo(b) < 0

a >= b

a.compareTo(b) >= 0

a <= b

a.compareTo(b) <= 0

Все сравнения преобразуются в вызовы compareTo, который должен возвращать Int.

Операторы делегирования свойств

Функции-операторы provideDelegate, getValue и setValue описаны в разделе Делегированные свойства.

Инфиксные вызовы именованных функций

Пользовательские инфиксные операции можно имитировать с помощью инфиксных вызовов функций.

12 августа 2026 г.
Функции с модификатором inlineПроверка неиспользуемого возвращаемого значения

© 2010–2026 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/operator-overloading.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API