Перегрузка операторов
Kotlin позволяет предоставлять пользовательские реализации предопределенного набора операторов для типов. Эти операторы имеют предопределенное символическое представление (например, + или *) и приоритет. Для реализации оператора предоставьте функцию-член или функцию-расширение со специфическим именем для соответствующего типа. Этот тип становится типом левой части для бинарных операций и типом аргумента для унарных.
Для перегрузки оператора отметьте соответствующую функцию модификатором operator:
interface IndexedContainer {
operator fun get(index: Int)
}
При переопределении перегрузок операторов можно опустить operator:
class OrdersList: IndexedContainer {
override fun get(index: Int) { /*...*/ }
}
Унарные операции
Унарные префиксные операторы
Выражение |
Перевод |
|---|---|
|
|
|
|
|
|
Эта таблица говорит о том, что при обработке компилятором, например, выражения +a, выполняются следующие шаги:
Определяется тип
a, пусть это будетT.Ищется функция
unaryPlus()с модификаторомoperatorи без параметров для получателяT, что означает функцию-член или функцию-расширение.Если функция отсутствует или неоднозначна, возникает ошибка компиляции.
Если функция присутствует и её тип возвращаемого значения —
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)"
}
Инкременты и декременты
Выражение |
Перевод |
|---|---|
|
|
|
|
Функции inc() и dec() должны возвращать значение, которое будет присвоено переменной, к которой применялась операция ++ или --. Они не должны изменять объект, к которому была вызвана операция inc или dec.
Компилятор выполняет следующие шаги для разрешения оператора в постфиксной форме, например a++:
Определяется тип
a, пусть это будетT.Ищется функция
inc()с модификаторомoperatorи без параметров, применимая к получателю типаT.Проверяется, что тип возвращаемого значения функции является подтипом
T.
Эффект вычисления выражения:
Сохранить начальное значение
aв временное хранилищеa0.Присвоить результат
a0.inc()вa.Возвратить
a0в качестве результата выражения.
Для a-- шаги полностью аналогичны.
Для префиксных форм ++a и --a разрешение работает аналогичным образом, и эффект:
Присвоить результат
a.inc()вa.Возвратить новое значение
aкак результат выражения.
Бинарные операции
Арифметические операторы
Выражение |
Перевод |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Для операций в этой таблице компилятор просто разрешает выражение в столбце Перевод.
Ниже приведён пример Counter класса, который начинается с заданного значения и может быть инкрементирован с помощью перегруженного + оператора:
data class Counter(val dayIndex: Int) {
operator fun plus(increment: Int): Counter {
return Counter(dayIndex + increment)
}
}
Оператор in
Выражение |
Перевод |
|---|---|
|
|
|
|
Для in и !in процедура аналогична, но порядок аргументов меняется.
Оператор индексированного доступа
Выражение |
Перевод |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Квадратные скобки переводятся в вызовы get и set с соответствующим числом аргументов.
Оператор вызова
Выражение |
Перевод |
|---|---|
|
|
|
|
|
|
|
|
Скобки переводятся в вызовы invoke с соответствующим числом аргументов.
Расширенные присваивания
Выражение |
Перевод |
|---|---|
|
|
|
|
|
|
|
|
|
|
Для операций присваивания, например, a += b, компилятор выполняет следующие шаги:
-
Если функция из правого столбца доступна:
Если соответствующая бинарная функция (т.е.
plus()дляplusAssign()) тоже доступна,aявляется изменяемой переменной, и тип возвратаplusявляется подтипом типаa, сообщить об ошибке (неоднозначность).Убедиться, что её тип возврата -
Unit, в противном случае сообщить об ошибке.Сгенерировать код для
a.plusAssign(b).
В противном случае попытаться сгенерировать код для
a = a + b(включая проверку типов: типa + bдолжен быть подтипомa).
Операторы равенства и неравенства
Выражение |
Перевод |
|---|---|
|
|
|
|
Эти операторы работают только с функцией equals(other: Any?): Boolean, которую можно переопределить для реализации пользовательской проверки равенства. Любая другая функция с тем же именем (например, equals(other: Foo)) не будет вызываться.
Операция == специальная: она переводится в сложное выражение, которое проверяет на null. null == null всегда истинно, а x == null для непустого x всегда ложно и не вызовет x.equals().
Операторы сравнения
Выражение |
Перевод |
|---|---|
|
|
|
|
|
|
|
|
Все сравнения переводятся в вызовы compareTo, которые должны возвращать Int.
Операторы делегирования свойств
provideDelegate, getValue и setValue операторные функции описаны в Делегированные свойства.
Вызовы infix для именованных функций
Вы можете имитировать пользовательские операции infix, используя вызовы функций infix.
© 2010–2023 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/operator-overloading.html