Kotlin Operator Overloading

Operator overloading lets you define what standard operators like +, -, *, ==, and [] do when applied to your own classes. Your custom types then feel as natural to use as built-in types.

The operator Keyword

data class Vector(val x: Double, val y: Double) {

    operator fun plus(other: Vector) = Vector(x + other.x, y + other.y)
    operator fun minus(other: Vector) = Vector(x - other.x, y - other.y)
    operator fun times(scale: Double) = Vector(x * scale, y * scale)
    operator fun unaryMinus() = Vector(-x, -y)

    override fun toString() = "Vector(${"%.2f".format(x)}, ${"%.2f".format(y)})"
}

fun main() {
    val v1 = Vector(3.0, 4.0)
    val v2 = Vector(1.0, 2.0)

    println(v1 + v2)       // Vector(4.00, 6.00)
    println(v1 - v2)       // Vector(2.00, 2.00)
    println(v1 * 2.0)      // Vector(6.00, 8.00)
    println(-v1)           // Vector(-3.00, -4.00)
}

Operator to Function Mapping


Operator  │ Function Name   │ Example
──────────┼─────────────────┼────────────────────
+         │ plus            │ a + b
-         │ minus           │ a - b
*         │ times           │ a * b
/         │ div             │ a / b
%         │ rem             │ a % b
-x        │ unaryMinus      │ -a
++        │ inc             │ a++
--        │ dec             │ a--
[]        │ get             │ a[i]
[]=       │ set             │ a[i] = v
in        │ contains        │ x in a
==        │ equals          │ a == b (from data class)
<, >      │ compareTo       │ a < b

Index Operator

class Matrix(private val data: Array) {
    operator fun get(row: Int, col: Int): Int = data[row][col]
    operator fun set(row: Int, col: Int, value: Int) { data[row][col] = value }
}

fun main() {
    val m = Matrix(arrayOf(intArrayOf(1,2,3), intArrayOf(4,5,6), intArrayOf(7,8,9)))
    println(m[1, 2])   // 6 (row 1, col 2)
    m[0, 0] = 99
    println(m[0, 0])   // 99
}

Comparison Operator

data class Version(val major: Int, val minor: Int, val patch: Int) : Comparable {
    override fun compareTo(other: Version): Int {
        if (major != other.major) return major.compareTo(other.major)
        if (minor != other.minor) return minor.compareTo(other.minor)
        return patch.compareTo(other.patch)
    }
    override fun toString() = "$major.$minor.$patch"
}

fun main() {
    val v1 = Version(2, 0, 0)
    val v2 = Version(1, 9, 5)
    val v3 = Version(2, 0, 1)

    println(v1 > v2)    // true
    println(v1 < v3)    // true

    val versions = listOf(v3, v1, v2)
    println(versions.sorted())   // [1.9.5, 2.0.0, 2.0.1]
    println("Latest: ${versions.max()}")  // Latest: 2.0.1
}

in Operator

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

fun main() {
    val range = NumberRange(10, 50)
    println(25 in range)    // true
    println(5 in range)     // false
    println(60 !in range)   // true
}

Practical Example: Money Class

data class Money(val amount: Double, val currency: String = "INR") {
    operator fun plus(other: Money): Money {
        require(currency == other.currency) { "Currency mismatch" }
        return Money(amount + other.amount, currency)
    }
    operator fun minus(other: Money): Money {
        require(currency == other.currency) { "Currency mismatch" }
        return Money(amount - other.amount, currency)
    }
    operator fun times(factor: Double) = Money(amount * factor, currency)
    operator fun compareTo(other: Money) = amount.compareTo(other.amount)
    override fun toString() = "$currency ${"%.2f".format(amount)}"
}

fun main() {
    val price    = Money(1500.0)
    val shipping = Money(100.0)
    val discount = Money(200.0)

    val total = price + shipping - discount
    println("Total: $total")           // INR 1400.00

    val withTax = total * 1.18
    println("With tax: $withTax")      // INR 1652.00

    println(price > discount)          // true
}

Leave a Comment

Your email address will not be published. Required fields are marked *