tutorial, no_image, kotlin,

Kotlin - no_image

Upendra Upendra Follow Jan 23, 2025 · 7 mins read
Kotlin - no_image
Share this

Operator overloading

Kotlin allows you to provide custom implementations for the predefined set of operators on types. These operators have predefined symbolic representation (like + or *) and precedence. To implement an operator, provide a member function or an extension function with a specific name for the corresponding type. This type becomes the left-hand side type for binary operations and the argument type for the unary ones.1

To overload an operator, mark the corresponding function with the operator modifier:

interface IndexedContainer {
    operator fun get(index: Int)
}

When overriding your operator overloads, you can omit operator:

class OrdersList: IndexedContainer {
    override fun get(index: Int) { /*...*/ }
}

The next operators can be overloaded:

Unary prefix operators

| Expression | Translated to | |—|—| | +a | a.unaryPlus() | | -a | a.unaryMinus() | | !a | a.not() |

This table says that when the compiler processes, for example, an expression +a, it performs the following steps:

  • Determines the type of a, let it be T;
  • Looks up a function unaryPlus() with the operator modifier and no parameters for the receiver T, that means a member function or an extension function;
  • If the function is absent or ambiguous, it is a compilation error;
  • If the function is present and its return type is R, the expression +a has type R.

As an example, here’s how you can overload the unary minus operator:

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)"
}

Increments and decrements

| Expression | Translated to | |—|—| | a++ | a.inc() | | a-- | a.dec() |

The inc() and dec() functions must return a value, which will be assigned to the variable on which the ++ or -- operation was used. They shouldn’t mutate the object on which the inc or dec was invoked.

The compiler performs the following steps for resolution of an operator in the postfix form, for example a++:

  • Determines the type of a, let it be T;
  • Looks up a function inc() with the operator modifier and no parameters, applicable to the receiver of type T;
  • Checks that the return type of the function is a subtype of T.

Arithmetic operators

| Expression | Translated to | |—|—| | 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) | | a..b | a.rangeTo(b) | | a..<b | a.rangeUntil(b) |

For the operations in this table, the compiler just resolves the expression in the Translated to column.

Example:2

fun main(args: Array<String>) {
    val p1 = Point(3, -8)
    val p2 = Point(2, 9)

    var sum = Point()
    sum = p1 + p2

    println("sum = (${sum.x}, ${sum.y})")
}

class Point(val x: Int = 0, val y: Int = 10) {

    // overloading plus function
    operator fun plus(p: Point) : Point {
        return Point(x + p.x, y + p.y)
    }
}

When you run the program, the output will be:

sum = (5, 1)

Indexed access operator

| Expression | Translated to | |—|—| | a[i] | a.get(i) | | a[i, j] | a.get(i, j) | | a[i_1, ..., i_n] | a.get(i_1, ..., i_n) | | a[i] = b | a.set(i, b) | | a[i, j] = b | a.set(i, j, b) | | a[i_1, ..., i_n] = b | a.set(i_1, ..., i_n, b) |

Square brackets are translated to calls to get and set with appropriate numbers of arguments.

Invoke operator

| Expression | Translated to | |—|—| | a() | a.invoke() | | a(i) | a.invoke(i) | | a(i, j) | a.invoke(i, j) | | a(i_1, ..., i_n) | a.invoke(i_1, ..., i_n) |

Parentheses are translated to calls to invoke with appropriate number of arguments.

Specifying an invoke operator on a class allows it to be called on any instances of the class without a method name.3

Let’s see this in action:

class Greeter(val greeting: String) {
    operator fun invoke(name: String) {
        println("$greeting $name")
    }
}

fun main(args: Array<String>) {
    val greeter = Greeter(greeting = "Welcome")
    greeter(name = "Kotlin")
    //this calls the invoke function which takes String as a parameter
}

Augmented assignments

| Expression | Translated to | |—|—| | 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) |

For the assignment operations, for example a += b, the compiler performs the following steps:

  • If the function from the right column is available:
    • If the corresponding binary function (that means plus() for plusAssign()) is available too, a is a mutable variable, and the return type of plus is a subtype of the type of a, report an error (ambiguity);
    • Make sure its return type is Unit, and report an error otherwise;
    • Generate code for a.plusAssign(b).
  • Otherwise, try to generate code for a = a + b (this includes a type check: the type of a + b must be a subtype of a).

Equality and inequality operators

| Expression | Translated to | |—|—| | a == b | a?.equals(b) ?: (b === null) | | a != b | !(a?.equals(b) ?: (b === null)) |

These operators only work with the function equals(other: Any?): Boolean, which can be overridden to provide custom equality check implementation. Any other function with the same name (like equals(other: Foo)) will not be called.

Comparison operators

| Expression | Translated to | |—|—| | a > b | a.compareTo(b) > 0 | | a < b | a.compareTo(b) < 0 | | a >= b | a.compareTo(b) >= 0 | | a <= b | a.compareTo(b) <= 0 |

All comparisons are translated into calls to compareTo, that is required to return Int.

Links

Operator overloading

Kotlin Operator Overloading

Invoke Operator & Operator Overloading in Kotlin

Further reading

Operator overloading in Kotlin

Conventions & Operator Overloading

How Can Kotlin Operator Overloading Help You?

Operator overloading

Mastering Kotlin indexed access operator

credit goes to @swayangjit
Join Newsletter
Get the latest news right in your inbox. We never spam!
Upendra
Written by Upendra Follow
Hi, I am Upendra, the author in Human and machine languages,I don't know to how 3 liner bio works so just Connect with me on social sites you will get to know me better.