Kotlin Operator Overloading

Kotlin allows you to provide custom implementations for predefined operators by defining functions with the operator modifier. This enables writing intuitive expressions for your own types.

1. Defining an Operator Function

Mark a function with operator and a specific name to overload the corresponding operator.

data class Point(val x: Int, val y: Int) {
  operator fun plus(other: Point) = Point(x + other.x, y + other.y)
}

val p1 = Point(1,2)
val p2 = Point(3,4)
println(p1 + p2)  // Point(x=4, y=6)

2. Arithmetic Operators

Overload +, -, *, /, % with names plus, minus, times, div, rem.

operator fun Point.minus(other: Point) = Point(x - other.x, y - other.y)
operator fun Point.times(scale: Int) = Point(x * scale, y * scale)

println(p1 - p2)     // Point(x=-2, y=-2)
println(p1 * 3)      // Point(x=3, y=6)

3. Unary Operators

Overload unaryPlus, unaryMinus, not, inc, dec.

operator fun Point.unaryMinus() = Point(-x, -y)
operator fun Point.inc() = Point(x + 1, y + 1)

println(-p1)        // Point(x=-1, y=-2)
println(p1.inc())   // Point(x=2, y=3)

4. Comparison Operators

Overload compareTo to support <, >, <=, >=.

data class Box(val volume: Int) {
  operator fun compareTo(other: Box) = volume - other.volume
}

val b1 = Box(10); val b2 = Box(20)
println(b1 < b2)    // true

5. Indexing Operators

Overload get and set to support bracket access.

class Matrix(val data: Array) {
  operator fun get(i: Int, j: Int) = data[i][j]
  operator fun set(i: Int, j: Int, v: Int) { data[i][j] = v }
}

val m = Matrix(arrayOf(intArrayOf(1,2),intArrayOf(3,4)))
println(m[1,0])      // 3
m[0,1] = 5
println(m[0,1])      // 5

6. Invoke Operator

Overload invoke to allow instances to be called like functions.

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

val greet = Greeter("Hello")
println(greet("Kotlin"))  // Hello, Kotlin

7. Contains Operator

Overload contains to support in checks.

class Range(val start: Int, val end: Int) {
  operator fun contains(x: Int) = x in start..end
}

val r = Range(1,5)
println(3 in r)      // true

8. RangeTo Operator

Overload rangeTo to support .. operator.

operator fun Point.rangeTo(other: Point) =
  listOf(this, other)  // example usage

val path = p1..p2
println(path)         // [Point(x=1,y=2), Point(x=3,y=4)]

9. Best Practices

Only overload operators when the meaning is intuitive. Keep implementations simple. Document custom operators. Avoid surprising behavior that deviates from conventional operator semantics.

10. Summary

Operator overloading enhances readability by allowing natural syntax for domain-specific types. Kotlin’s requirement for operator modifier is explicit, ensuring clarity about which functions provide operator behavior.

Previous: Kotlin Exception Handling

<