昨天我們介紹了 物件導向 (OOP)。
今天要來認識 Swift 另外兩個功能:列舉 (Enum) 與 協定 (Protocol)。
這兩個工具在 Swift 裡非常常用,能幫助我們建立更安全、更彈性的程式架構。
enum
用來定義一組有限的選項,能讓程式更具可讀性,也能避免使用註解來記憶值的意義。
假設我們要表達「方向」,如果不用 enum
,可能會用 Int
來表示:
// 1 = 北, 2 = 南, 3 = 東, 4 = 西
var dir = 1
這樣做可讀性差,還需要靠註解提醒自己「1 代表北方」,很容易出錯。
使用 enum
則能清楚定義每個方向,程式碼更容易閱讀與維護:
enum Direction {
case north
case south
case east
case west
}
var dir: Direction = .north
print(dir) // north
搭配 switch
使用時,可以針對不同情況執行對應的程式邏輯。
特別的是 Swift 的 switch
必須涵蓋所有情況,如果少寫某個 case,編譯器會報錯,避免遺漏:
switch dir {
case .north:
print("往北走")
case .south:
print("往南走")
case .east:
print("往東走")
case .west:
print("往西走")
}
每個 enum
case 都可以對應到一個「固定的值」,適合用在 有明確對應數字或字串 的情境。
enum Weekday: Int {
case monday = 1, tuesday, wednesday, thursday, friday, saturday, sunday
}
let today = Weekday.friday
print(today.rawValue) // 5
print(Weekday(rawValue: 5)) // friday
Int
會自動從 0 開始累加(上面範例指定從 1 開始)。rawValue
取出數值。Weekday(rawValue:)
由數值反推,但會回傳 Optional
。和 Raw Value 不同,關聯值可以讓每個 case 帶上額外資料。
適合用在需要同時表達「狀態 + 資料」的情境,例如 API 回傳結果:
enum LoginResult {
case success
case failure(message: String)
}
let result = LoginResult.failure(message: "密碼錯誤")
switch result {
case .success:
print("登入成功!")
case .failure(let msg):
print("登入失敗:\(msg)")
}
output
登入失敗:密碼錯誤
switch
中可以把值取出來使用。protocol
是一種「介面」,只定義需要有哪些屬性或方法,但不提供實作。
任何 class / struct / enum 只要遵守協定,就必須實作它的內容。
protocol Animal {
var name: String { get }
func speak()
}
struct Dog: Animal {
var name: String
func speak() {
print("\(name) : 旺!")
}
}
class Cat: Animal {
var name: String
init(name: String) {
self.name = name
}
func speak() {
print("\(name) : 喵!")
}
}
let pets: [Animal] = [Dog(name: "小黑"), Cat(name: "小花")]
for pet in pets {
pet.speak()
}
output
小黑 : 旺!
小花 : 喵!
Dog
用 struct
,Cat
用 class
,但都能遵守 Animal
協定。Protocol 可以搭配 Extension 提供「預設實作」,讓使用者不用重複寫相同程式碼。
protocol Greet {
func sayHello()
}
extension Greet {
func sayHello() {
print("Hello!")
}
}
struct Person: Greet {}
let p = Person()
p.sayHello() // Hello!
今天學到:
switch
安全又清楚