Swift 面向協(xié)議編程

1. Swift - the First POP Language

在WWDC15上盹牧,蘋果宣布Swift是世界上第一門面向協(xié)議編程(POP)語言。


2. 何為POP

實際上,POP就是通過協(xié)議擴展归露,協(xié)議繼承和協(xié)議組合的方式來設計需要編寫的代碼。

在Swift中斤儿,值類型優(yōu)先于類剧包。然而,面向對象的概念不能很好地與結構體和枚舉一起工作: 因為結構體和枚舉不能夠被繼承雇毫。因此玄捕,作為面向對象的一大特征—繼承就不能夠應用于值類型了踩蔚。

Sequences and collections in the standard library use value semantics, which makes it easy to reason about your code. Every variable has an independent value, and references to that value aren’t shared. For example, when you pass an array to a function, that function can’t accidentally modify the caller’s copy of the array.

值類型可以從協(xié)議繼承棚放,設置支持從多個協(xié)議繼承,因此馅闽,使用POP讓值類型成為了Swift中的一等公民飘蚯。


3. Protocol 一元復始,萬象更新

假設現(xiàn)在需要定義公共行為福也,如果使用類一般來說會在父類中定義功能局骤,子類依賴繼承可以得到父類的特性,或者自己重寫該方法添加其他行為暴凑。這其實是一個好的選擇峦甩,但是當方法越來越多或是需要實現(xiàn)在不同的類的功能,這個時候又需要給父類重新添加方法现喳,或者是干脆重新創(chuàng)建類凯傲。

舉個??:
假設:B、C 繼承自 A嗦篱,B1冰单、B2繼承自 B,C1灸促、C2繼承自 C
如果你發(fā)現(xiàn) B1 和 C2 具有某些共同特性诫欠,
在OC中如果完全使用繼承的做法是找到 B1 和 C2 的最近祖先涵卵,也就是 A,然后在 A 中添加一段代碼荒叼。于是還得重寫 B2 和 C1轿偎,禁用這個方法。

而協(xié)議通過描述實現(xiàn)類型應該實現(xiàn)什么來抽象建模被廓。因為可以實現(xiàn)多協(xié)議贴硫,一種類型可以被拆分為若干個抽象,這樣的話就可以將大的功能細化伊者。


4. 分守要津

1. Protocol Extensions

  1. 提供協(xié)議方法的默認實現(xiàn)和協(xié)議屬性的默認值英遭,從而使它們成為可選;符合協(xié)議的類型可以提供自己的實現(xiàn)亦渗,也可以使用默認的實現(xiàn)挖诸。
  2. 添加協(xié)議中未聲明的附加方法實現(xiàn),并且實現(xiàn)協(xié)議的任何類型都可以使用到這些附加方法法精。這樣就可以給遵循協(xié)議的類型添加特定的方法多律。
protocol Entity {
    var name: String {get set}
    static func uid() -> String
}

extension Entity {
    static func uid() -> String {
        return UUID().uuidString
    }
}

struct Order: Entity {
    var name: String
    let uid: String = Order.uid()
}
let order = Order(name: "My Order")
print(order.uid)



2. Protocol Inheritance

協(xié)議可以從其他協(xié)議繼承,然后在它繼承的需求之上添加功能搂蜓,因此可以提供更細粒度和更靈活的設計狼荞。

protocol Persistable: Entity {
    func write(instance: Entity, to filePath: String)
    init?(by uid: String)
}

struct InMemoryEntity: Entity {
    var name: String
}

struct PersistableEntity: Persistable {
    var name: String
    func write(instance: Entity, to filePath: String) { // ...
    }  
    init?(by uid: String) {
        // try to load from the filesystem based on id
    }
}



3. Protocol Composition

類、結構體和枚舉可以符合多個協(xié)議帮碰,它們可以采用多個協(xié)議的默認實現(xiàn)相味。這在概念上類似于多繼承。這種組合的方式不僅比將所有需要的功能壓縮到一個基類中更靈活殉挽,而且也適用于值類型丰涉。

struct MyEntity: Entity, Equatable, CustomStringConvertible {
    var name: String
    // Equatable
    public static func ==(lhs: MyEntity, rhs: MyEntity) -> Bool {
        return lhs.name == rhs.name
    }
    // CustomStringConvertible
    public var description: String {
        return "MyEntity: \(name)"
    }
}
let entity1 = MyEntity(name: "42")
print(entity1)
let entity2 = MyEntity(name: "42")
assert(entity1 == entity2, "Entities shall be equal")


5. 浮想聯(lián)翩

以下代碼會輸出什么???

protocol TheProtocol {
    func method1()
}

extension TheProtocol {
    func method1() {
        print("Called method1 from TheProtocol")
    }
    func method2() {
        print("Called method2 from TheProtocol")
    }
}

struct Struct1: TheProtocol {
    func method1() {
        print("called method1 from Struct1")
    }
    
    func method2() {
        print("called method2 from Struct1")
    }
}

let s1 = Struct1()
s1.method1()
s1.method2()

print("\n-----------------\n")

let s2:TheProtocol = Struct1()
s2.method1()
s2.method2()

print("\n-----------------\n")

結果參考流程圖:


flow_diagram.png




參考文獻:
Protocol Oriented Programming in Swift
Swift protocol extension method dispatch
Protocol Oriented Programming in Swift

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市斯碌,隨后出現(xiàn)的幾起案子一死,更是在濱河造成了極大的恐慌,老刑警劉巖傻唾,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件投慈,死亡現(xiàn)場離奇詭異,居然都是意外死亡冠骄,警方通過查閱死者的電腦和手機伪煤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來猴抹,“玉大人带族,你說我怎么就攤上這事◇案” “怎么了蝙砌?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵阳堕,是天一觀的道長。 經常有香客問我择克,道長恬总,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任肚邢,我火速辦了婚禮壹堰,結果婚禮上,老公的妹妹穿的比我還像新娘骡湖。我一直安慰自己贱纠,他們只是感情好,可當我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布响蕴。 她就那樣靜靜地躺著谆焊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪浦夷。 梳的紋絲不亂的頭發(fā)上辖试,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天,我揣著相機與錄音劈狐,去河邊找鬼罐孝。 笑死,一個胖子當著我的面吹牛肥缔,可吹牛的內容都是我干的莲兢。 我是一名探鬼主播,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼辫继,長吁一口氣:“原來是場噩夢啊……” “哼怒见!你這毒婦竟也來了俗慈?” 一聲冷哼從身側響起姑宽,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎闺阱,沒想到半個月后炮车,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡酣溃,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年瘦穆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赊豌。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡扛或,死狀恐怖,靈堂內的尸體忽然破棺而出碘饼,到底是詐尸還是另有隱情熙兔,我是刑警寧澤悲伶,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站住涉,受9級特大地震影響麸锉,放射性物質發(fā)生泄漏。R本人自食惡果不足惜舆声,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一花沉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧媳握,春花似錦碱屁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至腋粥,卻和暖如春晦雨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背隘冲。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工闹瞧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人展辞。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓奥邮,卻偏偏與公主長得像,于是被迫代替她去往敵國和親罗珍。 傳聞我的和親對象是個殘疾皇子洽腺,可洞房花燭夜當晚...
    茶點故事閱讀 44,960評論 2 355