Kotlin 運算子重載 (Operator Overloading)
Kotlin 允許我們為自定義的類別提供標準運算子 (如 +, -, *, /, == 等) 的實作。
這讓我們寫出來的程式碼更直觀、更像數學公式,而不只是一堆函式呼叫。
基本概念 (Syntactic Sugar)
在 Kotlin 中,運算子其實只是 特定名稱函式 的語法糖。
例如,當你寫 a + b 時,編譯器其實是幫你呼叫 a.plus(b)。
要啟用這個功能,我們必須在函式前面加上 operator 關鍵字。
範例:向量加法
假設我們有一個 Point 類別,我們希望可以直接用 p1 + p2 來相加。
data class Point(val x: Int, val y: Int) {
// 定義 + 運算子 (對應 plus 函式)
operator fun plus(other: Point): Point {
return Point(x + other.x, y + other.y)
}
}
fun main() {
val p1 = Point(10, 20)
val p2 = Point(30, 40)
val p3 = p1 + p2 // 自動呼叫 p1.plus(p2)
println(p3) // Point(x=40, y=60)
}
常見運算子對照表
算術運算子 (Arithmetic)
| 運算子 | 對應函式名 |
|---|---|
a + b | plus |
a - b | minus |
a * b | times |
a / b | div |
a % b | rem |
索引存取運算子 (Indexed Access)
這是讓你可以用 [] 來存取物件的關鍵!(像 List 和 Map 那樣)
| 運算子 | 對應函式名 |
|---|---|
a[i] | get(i) |
a[i] = b | set(i, b) |
class Box(val items: MutableList<String>) {
operator fun get(index: Int): String {
return items[index]
}
operator fun set(index: Int, value: String) {
items[index] = value
}
}
val box = Box(mutableListOf("A", "B"))
println(box[0]) // 呼叫 box.get(0)
box[1] = "C" // 呼叫 box.set(1, "C")
呼叫運算子 (Invoke)
讓物件可以像函式一樣被呼叫 obj()。
| 運算子 | 對應函式名 |
|---|---|
a() | invoke() |
a(i) | invoke(i) |
class Greeter(val name: String) {
operator fun invoke(msg: String) {
println("$name says: $msg")
}
}
val greet = Greeter("Miko")
greet("Hello!") // 等同於 greet.invoke("Hello!"),輸出: Miko says: Hello!
比較運算子 (Comparison)
| 運算子 | 對應函式名 |
|---|---|
a > b | compareTo > 0 |
a < b | compareTo < 0 |
a == b | equals (注意:equals 雖然也是 operator,但它是 Any 的成員,覆寫時只需 override 不需要加 operator 關鍵字) |
總結
operator關鍵字:必須加才能重載。- 固定名稱:不能隨便取名,必須對應標準的運算子名稱 (如
plus,minus,get)。 - 適度使用:不要濫用!只在語意清楚時使用 (例如向量相加),不要讓
+變成「儲存到資料庫」這種奇怪的邏輯。