Перегрузка операторов
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 описаны в Делегированные свойства.
Вызовы в стиле инфикс для именованных функций
Можно имитировать пользовательские операции в стиле инфикс, используя вызовы функций в стиле инфикс.
© 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