Operator Overloading in Kotlin
Kotlin allows you to define custom behavior for operators, making your code more expressive and intuitive.
Basic Operators
Arithmetic Operators
data class Point(val x: Int, val y: Int) {
operator fun plus(other: Point): Point {
return Point(x + other.x, y + other.y)
}
operator fun minus(other: Point): Point {
return Point(x - other.x, y - other.y)
}
operator fun times(factor: Int): Point {
return Point(x * factor, y * factor)
}
}
// Usage
val p1 = Point(1, 2)
val p2 = Point(3, 4)
val sum = p1 + p2
val diff = p2 - p1
val scaled = p1 * 2
Comparison Operators
data class Money(val amount: Double) {
operator fun compareTo(other: Money): Int {
return amount.compareTo(other.amount)
}
}
// Usage
val m1 = Money(10.0)
val m2 = Money(20.0)
val isGreater = m2 > m1
val isLess = m1 < m2
Advanced Operators
Index Access
class Matrix(val rows: Int, val cols: Int) {
private val data = Array(rows) { DoubleArray(cols) }
operator fun get(row: Int, col: Int): Double {
return data[row][col]
}
operator fun set(row: Int, col: Int, value: Double) {
data[row][col] = value
}
}
// Usage
val matrix = Matrix(2, 2)
matrix[0, 0] = 1.0
val value = matrix[0, 0]
Function Invocation
class Calculator {
operator fun invoke(x: Int, y: Int): Int {
return x + y
}
}
// Usage
val calc = Calculator()
val result = calc(5, 3)
Best Practices
- Use operator overloading sparingly
- Follow mathematical conventions
- Maintain consistency
- Document operator behavior
- Consider readability
Common Patterns
Range Operators
class Date(val year: Int, val month: Int, val day: Int) {
operator fun rangeTo(other: Date): List<Date> {
val dates = mutableListOf<Date>()
var current = this
while (current <= other) {
dates.add(current)
current = current.nextDay()
}
return dates
}
private fun nextDay(): Date {
// Implementation
return this
}
}
// Usage
val start = Date(2025, 1, 1)
val end = Date(2025, 1, 5)
val dates = start..end
Unary Operators
data class Complex(val real: Double, val imag: Double) {
operator fun unaryMinus(): Complex {
return Complex(-real, -imag)
}
operator fun unaryPlus(): Complex {
return this
}
}
// Usage
val c = Complex(1.0, 2.0)
val negated = -c
val same = +c
Performance Considerations
- Operator overloading has minimal overhead
- Consider using inline functions
- Be mindful of object creation
- Use primitive types when possible
Common Mistakes
- Overusing operator overloading
- Violating mathematical conventions
- Creating confusing operator behavior
- Ignoring performance implications
Conclusion
Operator overloading is a powerful feature in Kotlin that can make your code more expressive and intuitive. Use it wisely to create clear and maintainable code.