- 原文作者:NIkant Vohra
- 譯文出自:掘金翻譯計劃
- 譯者:Danny Lau
- 校對者:Jing Liu,lm
面向?qū)ο缶幊讨两褚呀?jīng)使用了數(shù)十年了,并且成為了構(gòu)建大型軟件約定俗成的標(biāo)準(zhǔn)杯矩。作為iOS編程的中心思想博助,遵循面向?qū)ο笠?guī)范來編寫一個 iOS 的應(yīng)用幾乎不可能實現(xiàn)。雖然面向?qū)ο笥泻芏鄡?yōu)點比如封裝性甸鸟,訪問控制和抽象性谋右,但是它也自帶有固有的缺點舔清。
大多數(shù)類的情況下觅彰,當(dāng)一個單繼承的類需要更多不同類中的函數(shù)功能時,你會傾向于使用多繼承來實現(xiàn)替裆。 但是大部分的編程語言不支持這一特性校辩,而且會導(dǎo)致類的繼承關(guān)系變得復(fù)雜。
在多線程環(huán)境下辆童,如果所有對象在函數(shù)中都是通過引用來傳遞會導(dǎo)致意想不到的問題宜咒。
因為類與類之間的高耦合性,為一個單獨的類寫測試單元會很困難胸遇。
下面是網(wǎng)上大量的對面向?qū)ο蟮谋г?/p>
All evidence points to OOP being bullshit | Pivotal
Object Oriented Programming is an expensive disaster which must end | Smash Company
Swift 嘗試引入一種叫做面向協(xié)議的編程新規(guī)范來解決傳統(tǒng)的面向?qū)ο缶幊讨泄逃械膯栴}荧呐。WWDC2015 演講做了一個令人驚嘆的關(guān)于面向協(xié)議編程的介紹汉形。我迫不及待的想推薦它了纸镊。
Swift 在最初的時候是包含值類型的概念。結(jié)構(gòu)體和枚舉都是 Swift 中的一等公民概疆,還擁有很多像 propertites, methods 和 extensions 等在大多數(shù)語言只有類才有的特點逗威。雖然在Swift中值類型不支持繼承,但是通過遵循協(xié)議的方式一樣能夠享受到面向協(xié)議的好處岔冀。
Ray Wunderlich 的面向協(xié)議編程的教程展示了它的能力凯旭。
Introducing Protocol-Oriented Programming in Swift 2
現(xiàn)在我將向你展示面向協(xié)議編程是如何點亮我的人生的。我的應(yīng)用程序遵循經(jīng)典的左側(cè)菜單導(dǎo)航模式(附帶一些選項)使套。這個應(yīng)用大概有十個不同的 view controller,它們都是繼承自一個擁有基礎(chǔ)函數(shù)和各個界面所需樣式的基類 view controller侦高。
和我的應(yīng)用相似的左側(cè)菜單的應(yīng)用例子
這個應(yīng)用依賴于 Webscokets 來與服務(wù)器交互。服務(wù)器可以隨時發(fā)送事件奉呛,而應(yīng)用根據(jù)用戶所在的界面來進(jìn)行相應(yīng)的事件響應(yīng)。舉個事件例子的話瞧壮,比如登出事件登馒,當(dāng)用戶收到了服務(wù)器關(guān)于這個狀態(tài)的事件時,應(yīng)用需要登出并顯示登錄界面咆槽。
在我腦中的第一想法是把登出事件寫在基礎(chǔ)的 view controller 里面,當(dāng)事件發(fā)生的時候,在需要的 view controller 進(jìn)行調(diào)用麦射。
// BaseViewController.swift
class BaseViewController {
func logout() {
//Perform Logout
print("Logout User")
}
}
這一步的問題就是并不是每個 view controller 都必須實現(xiàn)這個登出的功能,但是它還是都會繼承這個登出的函數(shù)法褥。此外不同的 view controller 需要響應(yīng)不同的事件茫叭,所以在基礎(chǔ) view controller 中包含所有的函數(shù)并沒有什么意義。
幸運地是面向協(xié)議編程拯救了我半等,我聲明一個 Logoutable 的協(xié)議揍愁,那些需要登出功能的 view controller 遵循這個 Logoutable 的協(xié)議就可以了杀饵。
// Logoutable.swift
protocol Logoutable {
func logout()
}
// ViewController.swift
class ViewController : Logoutable {
func logout() {
//Perform Logout
print("Logout User")
}
}
這一個進(jìn)步帶來的問題是我必須在每個需要遵循這個協(xié)議的 view controller 中重復(fù)這個登出函數(shù)的實現(xiàn)。
這正是面向協(xié)議編程在 Swift 中的閃光點切距,因為它給我們提供了協(xié)議拓展功能,可以在一個協(xié)議中定義一個默認(rèn)的函數(shù)的行為谜悟。所以我所需要做的僅僅是在 Logoutable 的協(xié)議中寫一個帶有默認(rèn)登出行為的實現(xiàn)的拓展,這樣這個函數(shù)對那些遵循這個協(xié)議的 view controller 的來說就是可選的葡幸。
//LogoutableExtension.swift
extension Logoutable where Self : BaseViewController {
func logout() {
//Perform Logout
print("Logout User")
}
}
面向協(xié)議編程完全就像魔法一樣,不定義任何復(fù)雜的繼承就夠就實現(xiàn)這些功能∥颠叮現(xiàn)在我就能為不同的事件定義不同的協(xié)議并且各自 view controller 就能夠遵循它所需要的協(xié)議。
面向協(xié)議編程是真正地點亮了我的人生蔑水,現(xiàn)在每當(dāng)我需要使用繼承或者其他面向?qū)ο蟮脑韥順?gòu)建我的代碼時,我會想這能否通過使用面向協(xié)議編程的方法來更好的完成這項工作丹擎。我不是說它是完美的解決方案但是它仍然值得一試。
如果你喜歡這篇文章的話鸥鹉,請推薦它,這樣其他人也可以欣賞它毁渗。