Overloading Operators
Need for operator overloading
Traditionally we use operators on numeric types to create expressions, for example, or . Operator overloading is a feature where the language extends the capability to use operators on user-defined data types.
Compare the two lines in the following code snippet:
bigInteger1.multiply(bigInteger2)
bigInteger1 * bigInteger2
The first line uses the multiply
method from the JDK. The second line uses the *
operator on the instances of BigInteger
; that operator comes from the Kotlin standard library. The second line takes less effort—both to write and to read—than the first line, even though they both accomplish the same thing. The operator *
makes the code look more natural, fluent, less code-like than the use of the multiply()
method. Java doesn’t permit us to overload operators on user-defined datatypes, but Kotlin does. That leads to greater fluency, less clutter, and makes it a joy to program in Kotlin.
Benefits of operator overloading
In addition to using operators like +
, -
, and *
on numeric types, languages that support operator overloading also permit using such operators on objects. For instance, given a reference today
of a Date class
, today + 2
may mean that’s two days from now.
Don’t Overuse Operator Overloading
Programmers have a love-hate relationship with operator overloading because it’s a feature that can be abused easily. For example, does today + 2 mean two days or two months from now? It’s not clear, and that’s frustrating to the person reading the code. Don’t use operator overloading unless it’ll be obvious to the reader.
When used correctly, the benefits of operator overloading are amazing. For example, wishList + appleWatch
is fairly intuitive; we’re appending an item to a List
. When overloading an operator on a user-defined class, we have to be careful to honor the intended behavior of the operator. For example, we know that +
is a pure function; it doesn’t modify either of the operands. The writer of +
on the class List
shouldn’t modify either of the operands provided to the +
operator. That’s part of the “used correctly” effort. The names used for the variables also contribute to the readability of code with operators, so pick names judiciously. For example, wishList + appleWatch
, rather than w + x
, is better to convey that we’re using overloaded operator +
on an instance of List
.
Since the JVM doesn’t support operator overloading (and Kotlin compiles down to Java bytecode), Kotlin makes operator overloading possible by mapping operators to specially named methods. For example, +
will result in a call to a plus()
method. By writing these specialized methods, you may overload operators on your own classes, although the precedence of operators is fixed and you can’t change the precedence. Also, using the extension functions that we’ll see soon, you may overload operators on third-party classes.
How is it done?
To overload an operator, define a function and mark it with the operator keyword. Here’s an example of overloading +
on a Pair<Int, Int>
to add a pair of numbers:
// pairplus.kts
operator fun Pair<Int, Int>.plus(other: Pair<Int, Int>) =
Pair(first + other.first, second + other.second)
The function is named plus()
which is the specialized method name for +
. It operates on an implicit object, the left operand, referenced using this
and on the right operand other
. Instead of writing this.first + other.first
, we used a short form first + other.first
to compute the sum of the first values in the two pairs. The plus()
extension function returns a new Pair<Int, Int>
, where the first value is sum of the first values in each of the given pairs and second is the sum of the second values in each of the given pairs.
To overload operators for your own classes, write the appropriate specialized methods as member functions within your classes. For example, here’s how you’d overload *
, on a class that represent a complex number, to multiply two complex numbers:
Get hands-on with 1400+ tech skills courses.