Swift 重載 (Overloading)
重載 (Overloading) 是指在同一個作用域中,可以使用相同的名稱來定義多個函式或運算子,只要它們的參數型別、參數數量或引數標籤不同即可。
Swift 會根據你呼叫時傳入的參數,自動決定要對應到哪一個實作。
函式重載 (Function Overloading)
函式重載讓程式碼更具可讀性,因為我們不需要為了處理不同型別而發明一大堆類似的函式名稱 (例如 printInt, printString, printDouble),而是統一使用一個名稱 (例如 print)。
1. 參數型別不同
func process(value: Int) {
print("Processing Int: \(value)")
}
func process(value: String) {
print("Processing String: \(value)")
}
process(value: 42) // 呼叫第一個版本
process(value: "Hello") // 呼叫第二個版本
2. 參數數量不同
func sum(a: Int, b: Int) -> Int {
return a + b
}
func sum(a: Int, b: Int, c: Int) -> Int {
return a + b + c
}
print(sum(a: 1, b: 2)) // 3
print(sum(a: 1, b: 2, c: 3)) // 6
3. 引數標籤不同
即使參數型別和數量都一樣,只要引數標籤 (Argument Label) 不同,也被視為不同的函式。
func move(to x: Int) {
print("Moving to \(x)")
}
func move(by x: Int) {
print("Moving by \(x)")
}
move(to: 10) // Moving to 10
move(by: 10) // Moving by 10
注意:Swift 不能僅此透過「回傳值型別不同」來進行重載,因為編譯器如果不看上下文,無法判斷你要呼叫哪一個。
運算子重載 (Operator Overloading)
Swift 允許我們為自定義的型別 (如 Struct 或 Class) 定義標準運算子 (如 +, -, *, ==) 的行為。這稱為運算子重載。
範例:向量加法
假設我們有一個二維向量 Vector2D:
struct Vector2D {
var x = 0.0, y = 0.0
}
我們希望能直接使用 + 號來相加兩個向量:
let v1 = Vector2D(x: 1.0, y: 2.0)
let v2 = Vector2D(x: 3.0, y: 4.0)
// let v3 = v1 + v2 // 這裡會報錯,因為 Swift 不知道怎麼加 Vector2D
實作「+」運算子
我們需要在 Vector2D 的 extension (或定義本體) 中,宣告一個 static func 來實作 +。
extension Vector2D {
static func + (left: Vector2D, right: Vector2D) -> Vector2D {
return Vector2D(x: left.x + right.x, y: left.y + right.y)
}
}
現在可以這樣用了:
let v3 = v1 + v2
print("x: \(v3.x), y: \(v3.y)") // x: 4.0, y: 6.0
前綴與後綴運算子 (Prefix / Postfix)
我們也可以重載前綴運算子,例如負號 -。
extension Vector2D {
// prefix 關鍵字表示這是前綴運算子
static prefix func - (vector: Vector2D) -> Vector2D {
return Vector2D(x: -vector.x, y: -vector.y)
}
}
let positive = Vector2D(x: 3.0, y: 4.0)
let negative = -positive
// negative 是 (-3.0, -4.0)
複合賦值運算子 (Compound Assignment)
例如 +=,這需要將左邊的參數標記為 inout,因為它會被修改。
extension Vector2D {
static func += (left: inout Vector2D, right: Vector2D) {
left = left + right // 複用上面定義的 +
}
}
var original = Vector2D(x: 1.0, y: 2.0)
let step = Vector2D(x: 3.0, y: 4.0)
original += step
// original 現在是 (4.0, 6.0)
Equatable 運算子 (==)
要讓自定義型別支援 == 和 !=,最簡單的方法是遵循 Equatable 協議。如果型別內的所有屬性都是 Equatable 的,Swift 會自動幫你生成實作!
struct Vector2D: Equatable {
var x = 0.0, y = 0.0
}
let va = Vector2D(x: 1, y: 1)
let vb = Vector2D(x: 1, y: 1)
print(va == vb) // true
如果你需要自定義比較邏輯,也可以手動重載 ==:
extension Vector2D {
static func == (lhs: Vector2D, rhs: Vector2D) -> Bool {
return lhs.x == rhs.x && lhs.y == rhs.y
}
}
關於更多自定義運算子的進階用法,可以參考 Swift 官方文件的 Advanced Operators。