Swift語言因爲先天的後發優點吸取了不少好的編程概念和特性,這些特性在給開發者帶來新可能的同時也進一步促進了語言自己的進化。這也是經歷三次Swift從入門到重學也不離不棄的緣由?。Swift語言的優點和特性大抵以下:程序員
跨平臺。Linux平臺的服務端正在發力,框架也在快速發展中。編程
開源給這門語言帶來了無限可能。數組
OOP、POP、函數式這些編程理念全支持架構
這篇文章將會對其中的POP概念進行簡單講解。POP概念的傳播起點大概就是在「喜新厭舊」的蘋果在2015年WWDC上鼓勵使用Value Type來替換Reference Type。可是咱們須要明白一點:開發世界沒有銀彈。POP做爲一個理念和特性有其適用場景並不能徹底替代OOP,後者存在幾十年是有理由的。併發
上面說了POP興起於Value Type被鼓勵推崇後,那麼咱們就有必要理解二者的區別。值類型和引用類型最根本的區別就在於複製後的二者的表現。作個類比:值類型複製動做至關於克隆了本身,你和克隆的對象之間是相互獨立的;引用類型複製動做後二者的關係至關於本身和影子。類比不是很貼切,可是不妨礙理解。下面用代碼來講明:框架
Class HumanClass { var name: String init(name: String) { self.name = name } } var classyHuman = HumanCalss(name: "Bob") classyHuman.name //Bob var newClassyHuman = classyHuman //複製一份 newClassyHuman.name = "Bobby" classyHuman.name //"Bobby"
當咱們改變newClassyHuman對象的name屬性後,類對象classyHuman也跟着發生了變化。編程語言
接下來看值類型:函數
struct HumanStruct { var name: String } var humanStruct = HumanStruct(name: "Bob") var newHumanStruct = humanStruct //一樣複製 newHumanStruct.name = "Bobby" humanStruct.name //"Bob"
拷貝對象的屬性改變並無影響到原對象。編碼
做爲幾十年前的一種理念,OOP能夠說已經在現代被用爛了,幾乎全部的編程語言都支持這一特性。Java、Ruby等語言的設計理念中幾乎將一切事物都看做對象,對象即中心、對象即真理。可是咱們反過頭來看OOP,其實能夠很清晰的發現一些固有的缺陷。spa
繼承機制要求你在開始以前就能設計好整個程序的框架、結構、事物間的鏈接關係。這要求開發者必須有很好的分類設計能力,由於結構天生對改動有抵抗特性。這也是爲何OOP領域中全部程序員都對重構諱莫如深,有些框架到最後代碼量急劇膨脹變得難以維護從而失控。
繼承機制帶來的另外一個問題就:子類中會存在無用的父類屬性和方法,而這些冗餘代碼給子類帶來的必定的風險,並且對於層級很深的代碼結構來講Bug修復將會成爲難題。
對象的狀態不是咱們的編碼的好友,相反是咱們的敵人。對象固有的狀態在分享和傳遞過程當中是很難追蹤調試的,尤爲在並行程序編碼中問題就更加明顯。OOP所帶來的可變、不肯定、複雜等特徵徹底與並行編程中倡導的小型化、核心化、高效化徹底背離。而免費午飯時代已經結束、摩爾定律的吃力表現意味着接下來的世界是屬於多核、並行、併發編程的。
這裏咱們順便看下Apple用OOP思想完成的UIKit框架:
總體結構設計其實很是的清晰,可是若是讓你在Apple對這個框架進行維護你有多少的自信可以出色完成任務?別說框架維護了,其實咱們大部分開發者都僅僅停留在框架的語言應用層面並無很大的耐心去釐清這個結構清晰的OOP框架。
你應該可以猜到了與OOP以引用類型Class爲基礎不一樣,POP理念的核心是值類型Struct。OOP是一種類金字塔的架構來搭建世界,POP則是一個扁平、非嵌套的代碼世界。
"A protocol defines a blueprint of methods, properties… The protocol can then be adopted by a class, structure, or enumeration" - Apple
上面是Apple對協議的定義說明,其中最關鍵的字眼莫過於「blueprint"。其實Protocal相似於籃球教練,他告訴球員們如何執行戰術、如何贏得比賽,可是他本人可能並不知道如何完成一個漂亮的大風車扣籃。
首先,咱們爲人類創建一個特徵藍圖。
protocol Human { var name: String {get set } var carrer: String {get set } func sayHi() }
上面的協議中,咱們除了聲明一些人類共有的特質沒有作任何其餘的事情。其中的{get set }僅僅只是表面這些屬性是可讀寫的,下面咱們讓運動員遵循該協議:
struct Athlete: Human { var name: String = "Kobe Bryant" var carrer: String - "Basketball Player" func satHi() { print("Hi,I'm \(name)" ) } }
一旦Struct遵循了Human協議,它就必須按照規則實現全部的協議屬性和方法。固然Xcode同窗會提醒你協議中的那些是你須要必須實現的,因此你沒必要懼怕遺忘了其中的部份內容。
在Protocol的世界中,咱們可使用OOP中的繼承概念對協議進行繼承造成協議樹。須要注意的是這一樣會帶來OOP中的惡果,不宜濫用。這裏咱們僅僅是爲了更加全面的介紹POP中協議所包含的各類能力。
咱們在Human協議基礎上實現SuperHuman的協議。
protocol SuperHuman: Human { var canFly: Bool { get set } } func punch() }
若是如今有一個Struct遵循了SuperHuman協議,那麼除了SuperHuman協議中的內容,咱們同時也要實現Human協議中的內容。
struct SuperSaiyan: SuperHuman { var name: String = "Goku" var race: String = "Asian" var canFly: Bool = true func sayHi() { print("Hi, I'm \(name)") } func punch() { print("Puuooookkk") } }
固然咱們也但是同時遵循多個協議,這在某種程度上來講至關於C++語言中類的多繼承的變通版本。
struct SuperSaiyan: SuperHuman, ProtocolAnother { }
協議拓展(Protocol Extension)是協議使用過程當中最強大的武器,下面咱們直接上碼:
// 會說英語的動物 protocol SuperAnimal { func speakEnglish() }
接下來咱們對其進行拓展:
extension SuperAnimal { func speakEnglish() { print("I speak English, pretty coo;, huh?") } }
最後咱們看看效果如何:
struct Donkey: SuperAnimal{ } var ramon = Donkey() ramon.speakEnglish() // "I speak English, pretty cool, huh?"
從上面的演示效果咱們能夠發現:經過協議拓展咱們給協議的遵循者一些默認的方法、屬性的實現。
若是我告訴你能夠在數組裏面同時保存Struct和Class對象而不用進行任何形式的類型轉換,你會做何感想?
是否是以爲難以想象,這確實有點突破常規,但同時在Swift中也是真實存在的。
直接上碼:
protocol Fightable { func legKick() } struct StructKangaroo: Fightable { func legKick() { print("Puuook") } } class ClassKangaroo: Fightable { func legKick() {print("Pakkkk") } } let structKang = StructKangaroo() let classKang = ClassKangaroo() var kangaroos: [Fightable] = [structKang, classKang] for kang in kangaroos { kang.legKick() } // "Puuook" // "Pakkkk"
咱們將同時採用Fightable協議的Class、Struct對象保存到了[Fightable]類型的數組中,而且能夠按照正常的數組同樣進行操做,是否是很神奇。
編程世界沒有銀彈,每一種理念都有其存在的價值。這篇文章中我簡單的介紹了POP的概念以及Protocol世界中的一些語法糖,真正的POP須要你本身在這些基礎知識和語法糖的上層去應用。