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