Kotlin operator overloading

Introduction

Since Kotlin provides user-defined types, it also provides the additional functionality to overload the standard operators, so that working with user-defined types is easier. All of the unary, binary, relational operators can be overloaded. The operators are overloaded either through the member functions or through extension functions. These functions are preceded by the operator modifier. There are standard functions for every type of operator that can be overloaded according to the usage.

Unary Operators

Below is a list of the various functions that can be defined for unary operators. These functions modify the calling instance.

For +x the corresponding function is x.unaryPlus()

For -x the corresponding function is x.unaryMinus()

For !x the corresponding function is x.not()

Here, x corresponds to the type for which the operator is defined. The overloaded functionality is defined within the respective functions.

Example

class UnaryOverload(var str:String) {
    // overloading the function
    operator fun unaryMinus() {
        str = str.reversed()
    }
}
// main function
fun main(args : Array<String>) {
    val obj = UnaryOverload("HELLO")
    println("Initial string is ${obj.str}")y
    //calling the overloaded function unaryMinus()
    -obj
    println("String after applying unary operator ${obj.str}")
}

Output

Initial string is HELLO
String after applying unary operator OLLEH

The increment and decrement operator can be defined for a type through the following functions. These function returns a new instance with the outcome of the expression.

For ++x the corresponding function is x.inc()

For – – x the corresponding function is x.dec()

Either used in postfix or prefix notation these functions work well in both the cases, with the same expected output, as one would expect when using prefix or postfix notations.

Example

class IncDecOverload(var str:String) {
    // overloading increment function
    operator fun inc(): IncDecOverload {
        val obj = IncDecOverload(this.str)
        obj.str = obj.str + 'a'
        return obj
    }
    // overloading decrement function
    operator fun dec(): IncDecOverload {
        val obj = IncDecOverload(this.str)
        obj.str = obj.str.substring(0,obj.str.length-1)
        return obj
    }

    override fun toString(): String {
        return str
    }
}
// main function
fun main(args: Array<String>) {
    var obj = IncDecOverload("Hello")
    println(obj++)
    println(obj--)
    println(++obj)
    println(--obj)
}

Output

Hello
Helloa
Helloa
Hello

Binary Operators

Below is a list of the binary operators and their equivalent functions to be defined. All these functions modify the calling instance.

Operator expression Corresponding function

For x1 + x2 the corresponding function is x1.plus(x2)

For x1 – x2 the corresponding function is x1.minus(x2)

For x1 * x2 the corresponding function is x1.times(x2)

For x1/ x2 the corresponding function is x1.div(x2)

For x1 % x2 the corresponding function is x1.rem(x2)

For x1..x2 the corresponding function is x1.rangeTo(x2)

Example of Kotlin program to overload the plus function –

class Object(var objName: String) {
    // Overloading the function
    operator fun plus(b: Int) {
        objName = "Name is $objName and data is $b"
    }
    override fun toString(): String {
        return objName
    }
}
// main function
fun main() {
    val obj = Object("Chair")
    // Calling the overloaded function
    obj+9
    println(obj)
}

Output:

Name is Chair and data is 9

The relational operators do not have any specific functions to be defined, to use relational operators on instances of a user-defined type, the type must implement the Comparable interface.

Other operators

Kotlin supports a wide range of operators, hence defining each for a type is not a good programming practice. Below are some of the other useful operators and their corresponding functions that can be overloaded is Kotlin.

For x1 in x2 the corresponding function is x2.contains(x1)

For x1 !in x2 the corresponding function is !x2.contains(x1)

For x[i] the corresponding function is x.get(i)

For x[i, j] the corresponding function is x.get(i, j)

For x[i] = b the corresponding function is x.set(i, b)

For x[i, j] = b the corresponding function is x.set(i, j, b)

For x() the corresponding function is x.invoke()

For x(i) the corresponding function is x.invoke(i)

For x(i, j) the corresponding function is x.invoke(i, j)

For x1 += x2 the corresponding function is x1.plusAssign(x2)

For x1 -= x2 the corresponding function is x1.minusAssign(x2)

For x1 *= x2 the corresponding function is x1.timesAssign(x2)

For x1 /= x2 the corresponding function is x1.divAssign(x2)

For x1 %= x2 the corresponding function is x1.remAssign(x2)

Conclusion

We have talked about the unary and binary operators hope you have fun exploring the other operators.

Happy Coding!