前言
好久沒有寫文章了,期末複習周也到了。在複習的同時順便開了一個專題,面向協議程式設計,[ 基礎篇 ],[ 進階篇 ],[ 實踐篇 ]。
介紹
首先,物件導向(OOP)大家並不陌生,蘋果的很多框架都是以這種形式進行構建的,但是,蘋果很矯情,2015年WWDC來,鼓勵使用 Value Type 值型別,也引出了這麼一個話題Protocol Oriented Programming 面向協議程式設計方式。關於值型別和引用型別,可以檢視官方文件或者這篇部落格[推薦略看一下]
OOP的發展已經很多年了,一直作為一種主流,蘋果的框架也是在一層又一層的繼承搭建起來的,但是在水果已經在不斷地強調使用Protocol了,自然有它的原因所在。
- 在OOP中,不支援多繼承的關係,往往定義一個BaseController,再往裡面新增方法,會造成程式碼很難維護(資料)
- 因為
class
是引用型別,所以可能會出現一些引用計數,引用迴圈等問題,你必須處理好這些問題。 - 子類繼承超類的時候,需要重寫很多你並不需要的例項或者方法。
“Instead of using a class, start with a protocol”.
認識Protocol
引用蘋果官方文件的說明,Protocol定義一張藍圖,並且能被class
,struct
,enum
繼承。而且,最重要的是支援多繼承的關係。
A protocol defines a blueprint of methods, properties, and other requirements ... The protocol can then be adopted by a class, structure, or enumeration.
正好今早學校寵物節?,下面我們定義一個Dog的協議。
struct Person {
var name: String
}
protocol Dog {
var name: String { get }
var owner: Person { get }
var age: Int { get }
}複製程式碼
然後宣告一個struct
遵循該協議
struct Husky: Dog {
let name: String // 例項的name不能修改
let owner: Person
var age: Int
// 不需要init( ) 也不需要override
// init(name: String, owner: Person, age: Int) {
// self.name = name
// self.owner = owner
// self.age = age
// }
}複製程式碼
協議的組合,和多繼承
我們的狗狗在寵物節是要去參加比賽的,所以我們定義一個Playable的協議
protocol Playable {
var GameName: String { get }
func playGame()
}複製程式碼
我們知道在OOP的世界裡,是不支援多繼承的關係的。Protocol的出現直接修補了這個DrawBack。
我們組合一下兩個協議
protocol DogCanPlay: Dog, Playable { }複製程式碼
接下來宣告一個struct
遵循這個協議,這樣這個struct就擁有了這兩個協議的所有屬性和方法,而且,編譯器還會告訴你,你缺少哪個屬性,哪個方法沒有宣告,非常方便。
struct PlayableDog: DogCanPlay {
var name: String
var owner: Person
var age: Int
func playGame() {
print("biubiubiu~")
}
var GameName: String
}複製程式碼
協議的組合原理也是多繼承的關係,上面的程式碼也可以這麼寫
struct PlayableDog: Dog, Playable {
var name: String
var owner: Person
var age: Int
func playGame() {
print("biubiubiu~")
}
var GameName: String
}複製程式碼
協議的擴充套件
不得不說,自Swift 2.0後,協議擴充套件【Protocol Extension】的出現,讓面向協議程式設計更加地powerful,強力推薦這個WWDC Session
extension DogCanPlay {
func playGame() { // 為協議新增預設實現
print("biubiu~~")
}
func loseGame() { //新增額外方法
print("??")
}
}複製程式碼
由於新增了預設實現,struct的定義就可以省去了playGame( )
struct Husky: DogCanPlay {
var name: String
var owner: Person
var age: Int
var GameName: String
}複製程式碼
例項一個變數試試~
var myDog = Husky(name: "小黃", owner: Person(name: "大東"), age: 4, GameName: "接飛盤")
myDog.playGame() // biubiu~
myDog.loseGame() // ??複製程式碼
協議的多型
我們知道,OOP有多型的特徵,在POP裡,也支援?
struct Dalmatian: DogCanPlay {
var name: String
var owner: Person
var age: Int
var GameName: String
}複製程式碼
建立兩個例項
let myDog = Husky(name: "小黃", owner: Person(name: "大東"), age: 4, GameName: "接飛盤")
let otherDog = Dalmatian(name: "達爾馬提亞狗", owner: Person(name: "洪**"), age: 4, GameName: "賽跑")複製程式碼
??
var competitionDog: [DogCanPlay] = [myDog, otherDog]
for dog in competitionDog {
print(dog.name)
//小黃
//達爾馬提亞狗
}複製程式碼
總結
基礎篇就介紹到這。往後,我會介紹protocol中where
語法的使用,還有POP在UIKit的實踐。喜歡請點個贊?
ARC and Memory Management in Swift
Introducing Protocol-Oriented Programming in Swift 3