Перегрузка операторов
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–2022 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/operator-overloading.html