在還沒接觸 Swift 時,時常會用到物件導向(OOP, Object-Oriented Programming)來開發。OOP 是在開發時創造出許多 objects(struct or class),然後重複利用它們, 然後讓 obects 間彼此繼承以提高軟體的重用性、靈活性和擴充功能性。
Don’t start with a class, start with a protocol.
Apple 在 WWDC 2015 發表會上將 Swift 寫作方式定義成 Protocol-Oriented Programming。其概念跟 OOP 其實很雷同,只不過是從重複利用 objects 改成重複利用 protocol。本篇就來聊聊這種寫作方式。
首先先創建一個 JobSeeker Protocol,裡頭有兩個 property: job 及 caniOS,
接著利用 Protocol 去規範了開發者在創建一個求職者時,必須要填入他想找的工作類型,以及會不會開發 iOS。
enum Job {
case iOS
case android
}
protocol JobSeeker {
var seekFor: Job { get }
var caniOS: Bool { get }
}
struct Gavin: JobSeeker {
let seekFor: Job
let caniOS: Bool
}
let gavin = Gavin(seekFor: .iOS, caniOS: true)
在尋找 iOS 工作機會的人當中,應該都會開發 iOS 才對,只是不一定會寫 Swift,所以我們在這邊再加上另一個 Protocol,並實作到 Gavin 上:
protocol Swiftable {
var knowSwift: Bool { get }
}
struct Gavin: JobSeeker, Swiftable {
let seekFor: Job
let caniOS: Bool
let knowSwift: Bool
}
到這邊應該會發現都已經有了 knowSwift 這一 property 怎麼還需要另一個 caniOS property?
這時候就該是使用 Protocol-Oriented Programming 的精神: Protocol Extension 來改寫。
enum Job {
case iOS
case android
}
protocol Swiftable {
var knowSwift: Bool { get }
}
protocol JobSeeker {
var seekFor: Job { get }
var caniOS: Bool { get }
}
extension JobSeeker {
var caniOS: Bool {
return self is Swiftable
}
}
struct Gavin: JobSeeker, Swiftable {
let seekFor: Job
let knowSwift: Bool
}
let gavin = Gavin(seekFor: .iOS, knowSwift: true)
print("Gavin is seeking for \(gavin.seekFor) and can develop iOS: \(gavin.caniOS)”)
//Gavin is seeking for iOS and can develop iOS: true
使用了 Protocol Extension 後讓 source code 擁有了更大的彈性。像上面這段程式,當有實作 JobSeeker 的程式,是否也實作了 Swiftable 這個 Protocol。如果會 Swift 就等於他會開發 iOS,於是在 Extension JobSeeker 中會去塞個預設值給 caniOS。
再來創造另一個求職者 Avin:
struct Avin: JobSeeker {
let seekFor: Job
}
let avin = Avin(seekFor: .android)
print("Avin is seeking for \(avin.seekFor) and can develop iOS: \(avin.caniOS)”)
// Avin can develop iOS: false
因為 Avin 是想尋找 Android 的工作,所以常理來說他並不會寫 iOS 程式,因此就不需要再去多做一個判斷,因為在 Extension JobSeeker 時就已經做好了。
假如某天 Avin 學會了 Swift 後要找 iOS 的工作時,只需將 caniOS property 加入 Avin 這個 object 而不需要改動到整個 protocol 即可達到所要的效果。
Reference
WWDC 2015