operator modifier that provides a custom implementation for a predefined language operator. This mechanism, known as operator overloading, allows instances of user-defined types to be manipulated using standard symbolic operators (such as +, ==, >, or []) by mapping those symbols to specific, statically resolved function calls.
Syntax
An operator function is defined using theoperator keyword, followed by a strictly predefined function name that corresponds to the target operator.
Core Mechanics
Kotlin does not allow the creation of custom operator symbols. Instead, it relies on a desugaring process during compilation. When the compiler encounters a supported operator, it translates the symbolic expression into a standard method invocation targeting the corresponding operator function. For example, the binary expressiona + b is translated by the compiler into a.plus(b).
Rules and Constraints
- Explicit Modifier: The
operatorkeyword is mandatory. If a function is namedplusbut lacks theoperatormodifier, it cannot be invoked using the+symbol; it can only be called via standard dot-notation (a.plus(b)). - Predefined Naming: The function name must exactly match the Kotlin specification for the desired operator (e.g.,
plus,get,compareTo). - Scope: Operator functions must be declared either as member functions within a class or as extension functions.
- Arity: The number of parameters is dictated by the specific operator type. Unary arithmetic operators take no parameters, and binary arithmetic operators take exactly one parameter. However, indexed access (
get,set) and invocation (invoke) operators can take an arbitrary number of parameters. - Overloading: Operator functions can be overloaded for the same symbol by providing different parameter types, similar to standard functions.
- The
equalsException: The equality operator (==) is a strict exception to the scope and overloading rules. It must be declared as a member function overridingAny.equals(other: Any?). Extension functions forequalsare ignored by the compiler, and it cannot be overloaded with custom parameter types.
Operator to Function Mappings
Below are the categories of operators and their corresponding compiler translations.Unary Prefix Operations
| Expression | Translated Function Call |
|---|---|
+a | a.unaryPlus() |
-a | a.unaryMinus() |
!a | a.not() |
Increments and Decrements
Unlike simple method calls,inc() and dec() must return a value, which the compiler then assigns back to the variable. The compiler automatically handles the temporary variables required to support prefix vs. postfix return semantics.
| Expression | Translated Assignment |
|---|---|
a++ / ++a | a = a.inc() |
a-- / --a | a = a.dec() |
Arithmetic Binary Operations
| Expression | Translated Function Call |
|---|---|
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) |
Augmented Assignment Operations
For augmented assignments, the compiler first checks for the specificAssign function (e.g., plusAssign). If it is not available, it falls back to the standard binary operator and assigns the result back to the variable (e.g., a = a.plus(b)), provided the variable is mutable.
Ambiguity Rule: If both the augmented assignment function (e.g., plusAssign) and the corresponding binary function (e.g., plus) are defined and applicable to a mutable variable, the compiler does not fall back; instead, it reports an ambiguity error.
| Expression | Translated Function Call |
|---|---|
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) |
Equality and Inequality Operations
Equality operators are translated to theequals function, incorporating null-safety checks under the hood.
| Expression | Translated Function Call |
|---|---|
a == b | a?.equals(b) ?: (b === null) |
a != b | !(a?.equals(b) ?: (b === null)) |
Comparison Operations
All comparison operators translate to calls tocompareTo, which must return an Int.
| Expression | Translated Function Call |
|---|---|
a > b | a.compareTo(b) > 0 |
a < b | a.compareTo(b) < 0 |
a >= b | a.compareTo(b) >= 0 |
a <= b | a.compareTo(b) <= 0 |
Range Operations
| Expression | Translated Function Call |
|---|---|
a..b | a.rangeTo(b) |
a..<b | a.rangeUntil(b) |
Collection and Access Operations
| Expression | Translated Function Call |
|---|---|
a in b | b.contains(a) |
a !in b | !b.contains(a) |
a[i] | a.get(i) |
a[i, j] | a.get(i, j) |
a[i] = b | a.set(i, b) |
a[i, j] = b | a.set(i, j, b) |
Invocation
| Expression | Translated Function Call |
|---|---|
a() | a.invoke() |
a(i) | a.invoke(i) |
a(i, j) | a.invoke(i, j) |
Implementation Examples
Operator functions can be implemented as members of a class or as extensions to existing classes. Member Operator Function:Tired of Poor Kotlin Skills? Fix That With Deep Grasping!Learn More





