iT邦幫忙

2025 iThome 鐵人賽

DAY 14
0
Mobile Development

Swift iOS 開發新手村:從入門到 AI 聊天室系列 第 14

Day 14|Swift 協定導向程式設計:打造你的 Swift 程式規範!

  • 分享至 

  • xImage
  •  

昨天我們學會了用 閉包(Closure) 讓「功能」變得靈活。今天,我們要讓「資料型別」本身也變得同樣靈活!

想像一下,我們要如何保證 一隻鳥一架飛機 這兩種截然不同的東西,都一定擁有fly()這個方法?答案就是讓它們簽署同一份「行為契約」。

在 Swift 中,這份契約就是 協定(Protocol)。它定義了一套所有型別都可以承諾遵守的規範,是實現彈性、模組化設計,以及Delegate等重要模式的基礎。準備好來當個制定規則的架構師了嗎?

今日學習重點

  • 協定的基礎:學習如何定義一份「行為契約」,並要求屬性、方法與建構器。
  • 協定作為型別:探索如何將協定當作通用型別,並透過 擴展(Extension) 提供預設功能。
  • 委任模式(Delegation):深入了解 iOS 開發中最重要的設計模式之一。
  • 進階技巧:掌握協定的繼承、合成,以及如何用 isas? 檢查遵循狀態。

協定定義與要求

首先,我們定義一份「飛行合約」,要求所有會飛的東西,都必須有名字和飛行方法:

// 定義一份「可飛行」的協定
protocol Flyable {
    // 要求:必須有一個可讀取的「名字」屬性
    var name: String { get }
    
    // 要求:必須有一個「飛行」的方法
    func fly()
}

遵循協定

現在,我們讓 Bird(結構)和 Plane(類別)這兩個完全不同的型別,都來簽署並遵守這份合約:

struct Bird: Flyable {
    var name: String
    
    func fly() {
        print("鳥 \(name) 正在展翅高飛。")
    }
}

class Plane: Flyable {
    var name: String
    
    init(name: String) {
        self.name = name
    }
    
    func fly() {
        print("飛機 \(name) 正在引擎全開地飛行。")
    }
}

協定作為型別

協定最酷的地方,就是可以當作一個「通用型別」來使用。我們可以建立一個只認識 Flyable 的函式,它不在乎傳進來的是鳥還是飛機。


let sparrow = Bird(name: "麻雀")
let boeing747 = Plane(name: "波音747")

// 這個函式只認得「會飛的東西」,不關心具體型別
func letItFly(flyer: Flyable) {
    print("準備起飛...")
    flyer.fly()
}

letItFly(flyer: sparrow)    // 傳入 Bird
letItFly(flyer: boeing747) // 傳入 Plane

協定擴展:預設實作

假設我們希望所有會飛的東西,都能「降落」。我們可以透過擴展協定,直接為所有遵循者加上預設的降落功能:

extension Flyable {
    func land() {
        print("\(name) 降落了。")
    }
}

// 現在不管是鳥還是飛機,都會自動獲得 land() 方法!
sparrow.land()    // 印出 麻雀 降落了。
boeing747.land() // 印出 波音747 降落了。

委任模式(Delegation):協定的典型應用

委任模式是協定最重要的應用,需要一個完整的範例來展示「委託方」和「受委託方」的互動:

protocol TaskDelegate {
    func didFinishTask(taskName: String) // 任務完成後要回報
}

// 2. 建立「工人」(委託方),他身上有個「監工」的屬性
class Worker {
    var delegate: TaskDelegate? // 監工是誰還不確定,所以是 Optional

    func doTask() {
        print("工人:開始執行任務...")
        // ...執行任務中...
        print("工人:任務完成!")
        
        // 透過合約,向監工回報
        delegate?.didFinishTask(taskName: "清洗窗戶")
    }
}

// 3. 建立「經理」(受委託方),他同意遵守「任務合約」
class Manager: TaskDelegate {
    func didFinishTask(taskName: String) {
        print("經理:收到回報,\(taskName) 任務已完成。做得很好!")
    }
}

// --- 實際應用 ---
let worker = Worker()
let manager = Manager()

// 把經理指派為工人的監工
worker.delegate = manager

// 工人開始工作,完成後會自動向他的監工(經理)回報
worker.doTask()

進階:協定繼承與合成

協定能繼承其他協定,組合更多要求。
使用 SomeProtocol & AnotherProtocol 表示同時遵循多個協定:

protocol SomeProtocol {}
protocol AnotherProtocol {}

protocol CombinedProtocol: SomeProtocol, AnotherProtocol {
    // 繼承多個協定要求
}

型別檢查與轉換

有時候,我們雖然知道一個物件是Flyable,但可能想進一步確認它到底是Bird還是Plane,並存取其特有的屬性。這時就可以使用isas?

// 建立一個包含不同型別的 Flyable 陣列
let flyers: [Flyable] = [Bird(name: "老鷹"), Plane(name: "F-22猛禽戰鬥機")]
for flyer in flyers {
    // 使用 is 來檢查型別
    if flyer is Bird {
        print("\(flyer.name) 是一隻鳥。") // 正確寫法
    } else if flyer is Plane {
        print("\(flyer.name) 是一架飛機。") // 正確寫法
    }

    // 使用 as? 來嘗試安全轉換型別
    if let plane = flyer as? Plane {
        print("確認過眼神,\(plane.name) 是一架飛機沒錯。")
    }
}

小結一下

今天我們深入探索了 Swift 的核心靈魂:協定(Protocol)!我們學會了協定如何作為一份「行為契約」,只定義規範而不提供實作,並讓任何classstructenum都能遵循它。

在此基礎上,我們解鎖了協定的強大應用:將它作為型別來提升程式彈性、透過擴展提供預設實作來減少重複的程式碼,以及應用在 委任模式(Delegation) 上來降低程式碼的耦合度。

最重要的是,你理解了協定的核心思想:「專注於行為而非實作細節」,這將幫助你打造出更靈活、更易於維護的程式架構。

🌟 明天預告

這一天終於來了! 經過 14 天的語法修煉,我們終於要告別黑底白字的 Playground,正式踏上打造真實 App 畫面的旅程!

明天,我們將正式啟動 Xcode 的 Storyboard,你將學會如何像設計師一樣,用滑鼠拖曳出按鈕與標籤,並見證最神奇的一刻:透過 IBOutlet 將畫面元件與你的程式碼串連起來。

這將是你第一次讓程式碼真正「看得見」、能與使用者「互動」。準備好打造你的第一個 iOS App 了嗎?

敬請期待《Day 15|Xcode 正式啟程:從語法邁向實作,建立你的第一個 iOS App!》


上一篇
Day 13|Swift 閉包入門:寫出精煉又強大的程式!
下一篇
Day 15|Xcode 正式啟程:從語法邁向實作,建立你的第一個 iOS App!
系列文
Swift iOS 開發新手村:從入門到 AI 聊天室16
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言