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须要你本身在这些基础知识和语法糖的上层去应用。