In Kotlin, operator overloading is supported through the operator keyword. This allows you to define your own logic for standard operators (+, -, *, [], ==, etc.) for user-defined types:
operator modifier.Example:
data class Vec2(val x: Int, val y: Int) { operator fun plus(other: Vec2) = Vec2(x + other.x, y + other.y) } val a = Vec2(1,2) val b = Vec2(2,3) val c = a + b // will invoke operator fun plus
Nuances and best practices:
== and equals should be consistent).What is the difference between overloading the
==operator and overriding theequals()method?
Answer: The == operator in Kotlin always calls the equals() method (with a preliminary null check). If you define operator fun equals(other: Any?): Boolean, the == operator will always use this method. You cannot make == and equals() work differently.
data class Point(val x: Int, val y: Int) { override operator fun equals(other: Any?): Boolean { ... } } val a = Point(1,2) val b = Point(1,2) println(a == b) // will invoke a.equals(b)
History
Overloaded the compareTo operator without explicit semantics:
In the Point class, operator fun compareTo was defined for the ability to use it in sorting. However, "greater than" and "less than" had no explicit meaning, different team members wrote different logic. The result was confusing bugs during collection sorting.
History
Forgot about symmetry of operators for mutual types:
A developer implemented operator fun plus(a: Matrix, b: Vector): Matrix, but did not ensure functionality for Vector + Matrix, as they did not implement a symmetric function. As a result, the expression vector + matrix did not compile, only matrix + vector worked. This led to bugs in many parts of the code.
History
Incorrect operator get overloading:
A developer created a custom class, overloading operator fun get(index: Int): Foo. They did not add boundary checks — and attempting to access a non-existent element returned an object with invalid fields instead of throwing an exception — which led to "invisible" errors in business logic.