Перегрузка операторов
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