← Back to Kotlin Course | Chapter 10: Extension Functions & Properties | Lesson 4 of 6

Operator Overloading

Operator overloading lets you teach ordinary symbols, like plus, how to work on your own custom types, not just numbers.
Syntax
kotlin
class ClassName(val value: Type) {
    operator fun plus(other: ClassName): ClassName = ClassName(/* combine */)
    operator fun get(index: Int): Type = value
    override fun equals(other: Any?): Boolean = /* compare */
}

a + b
a[0]

Overloading the Plus Operator

Defining an operator fun plus(other: Type) inside a class lets instances of that class be combined with the + symbol directly.

Example: Overloading the Plus Operator

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

// Entry point: execution of the program starts here
fun main() {
    // Declare a read-only variable `p1`, set to `Point(1, 2)`
    val p1 = Point(1, 2)
    // Declare a read-only variable `p2`, set to `Point(3, 4)`
    val p2 = Point(3, 4)
    // Print `p1 + p2` to the console, with a trailing newline
    println(p1 + p2)
}

Overloading Comparison with equals

Overriding equals() (which data classes do automatically) defines what == means for a type, letting two separate instances be considered logically equal based on their content.

Example: Overloading Comparison with equals

markup
// Define a class `Money`
class Money(val cents: Int) {
    override fun equals(other: Any?): Boolean {
        // Return `other is Money && other.cents == cents` from this function
        return other is Money && other.cents == cents
    }
    override fun hashCode(): Int = cents
}

// Entry point: execution of the program starts here
fun main() {
    // Declare a read-only variable `a`, set to `Money(500)`
    val a = Money(500)
    // Declare a read-only variable `b`, set to `Money(500)`
    val b = Money(500)
    // Print "Equal: ${a == b}" to the console, with a trailing newline
    println("Equal: ${a == b}")
}

Overloading Index Access with get

Defining operator fun get(index: Type) lets instances of a class support square-bracket indexing, just like a List or Array.

Example: Overloading Index Access with get

markup
// Define a class `Grid`
class Grid(val values: List<List<Int>>) {
    operator fun get(row: Int, col: Int): Int = values[row][col]
}

// Entry point: execution of the program starts here
fun main() {
    // Declare a read-only variable `grid`, set to `Grid(listOf(listOf(1, 2), listOf(3, 4)))`
    val grid = Grid(listOf(listOf(1, 2), listOf(3, 4)))
    // Print "Value at (1, 0): ${grid[1, 0]}" to the console, with a trailing newline
    println("Value at (1, 0): ${grid[1, 0]}")
}

Making an Object Callable with invoke

Defining operator fun invoke(...) lets an instance of a class be called directly like a function, using parentheses right after the object's name.

Example: Making an Object Callable with invoke

markup
// Define a class `Greeter`
class Greeter(val greeting: String) {
    operator fun invoke(name: String): String = "$greeting, $name!"
}

// Entry point: execution of the program starts here
fun main() {
    // Declare a read-only variable `greeter`, set to `Greeter("Hello")`
    val greeter = Greeter("Hello")
    // Print `greeter("Kotlin")` to the console, with a trailing newline
    println(greeter("Kotlin"))
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Forgetting the operator keyword before a function named to match an operator convention, such as plus, which is required for the overload to actually work.
  2. Overloading an operator in a way that surprises users, such as making + perform subtraction, which harms readability rather than helping it.
  3. Not matching the exact expected function signature (name and parameter count) for the operator being overloaded.
Chapter Summary
  • Operators like +, -, *, and == map to specific function names (plus, minus, times, equals) that can be overloaded with the operator keyword.
  • Overloaded operator functions must be marked operator fun and follow the exact expected signature for that operator.
  • Overloading [] access uses get/set, and calling an object like a function uses invoke.
  • Operator overloads should behave in a way that matches the operator's normal, expected meaning to keep code readable.
🔒

Chapter Quiz — Complete all 6 topics to unlock

0/6 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.