Swift 面向协议编程入门

本文讲的是Swift 面向协议编程入门,

面向对象编程的思想没毛病,但老铁你可以更 666 的

上图这个人不是我,但这就是使用面向协议编程替换掉面向对象编程之后的感觉。

介绍

这个教程也是为了那些不知道类和结构体根本区别的人写的。我们都知道在结构体里是没有继承的,但是为什么没有呢?

如果你不知道上面问题的答案,那么花几秒钟看下下面的代码。请再次原谅我的排版,我已经让它尽可能的简单明了了。

注:译者已经改过排版了

class HumanClass {
    var name: String
    init(name: String) {
        self.name = name
     }
}

var classyHuman = HumanClass(name: "Bob")
classyHuman.name // "Bob"

var newClassyHuman = classyHuman // Created a "copied" object

newClassyHuman.name = "Bobby"
classyHuman.name // "Bobby"

当我把 newClassyHuman 的 name 属性设为 “Bobby” 之后,原来对象 classyHuman 的 name 属性也会变成 “Bobby” 。

现在,让我们来看一下结构体的情况。

struct HumanStruct {
	var name: String
}

var humanStruct = HumanStruct(name: "Bob" )
var newHumanStruct = humanStruct // Copy and paste

newHumanStruct.name = "Bobby"
humanStruct.name // "Bob"

你看到它们的不同之处了么?对拷贝出来的对象的 name 属性的改变并没有影响到原有的 humanStruct 对象。

在类中,当你对一个变量进行拷贝的时候,两个变量都指向内存中的同一个对象。两个中的任何一个变量中的改变都会影响另外一个变量(引用类型)。然而在结构体中,你是通过创建了一个新的对象(值类型)来实现简单的拷贝和复制的。

如果你还没有理解的话,试着把之前那一段再看一遍。如果还是不理解的话,你可以看下我做的这个视频。

结构体 vs 类课程

再见面向对象编程

你可能会很奇怪为什么我所讲的这些好像和面向协议编程的话题一点关系都没有。然而,在我讲使用面向协议编程替换面向对象编程的好处之前,是必须要理解引用类型和值类型的区别的。

使用面向对象编程当然有优点的,但是相对的缺点也存在。

  1. 当时构建子类的时候,你必须继承一些你不需要的属性和方法。你的对象变得不必要的虚胖。
  2. 当时使用了大量的父类(太多继承层级),在不同的类里面跳来跳去编写代码或者修复 bug 都会变得非常棘手。
  3. 因为对象都是指向内存中的同一个空间,如果你创建了一个拷贝,并且对它的属性进行了一点小改动,它会影响到其余的对象。(引用导致的易变性)

顺便说一下,来看一下 UIKit 框架是怎么用面向对象编程来写的。

如果你作为软件工程师第一次去苹果工作的话,你能使用这些代码么?我的意思是我们开发者在界面层使用中都有过很痛苦的经历。

有人说过面向对象编程就是通过模块化的模式来写意大利面条式的代码。如果你想找到更多关于面向对象编程的缺点的话,看这里的咆哮 1 、咆哮 2 、咆哮 3 、咆哮 4 。

欢迎使用面向协议编程

你可能已经猜到了,和类不一样的是,面向协议编程的基础是值类型。不再是引用了,和你之前看到的金字塔结构不一样,面向协议所提倡的是扁平化和去嵌套的代码。

可能会有点吓到你,我将引出的是苹果的定义。

“协议定义了方法、属性的蓝图…… 然后类、结构体或枚举类型都能够使用协议” — 苹果

你现在唯一需要记住的就是这个词语,“蓝图”。

协议就好像是一个篮球教练,他告诉他的队员该怎么做,但是他却不知道怎么扣篮。

真正的使用面向协议编程

首先,我们来生成人的蓝图。

protocol Human {
	var name: String { get set }
	var race: String { get set }
	func sayHi()
}

就像你看到的,在协议里是没有真正的”扣篮“。它只会告诉你有那么个东西的存在。顺便说一下,现在你不需要担心 { get set } 。它只是表示你可以改变这个属性的值并能够获取这个属性。除非你用的是一个计算属性话,现在是不用担心的。

现在让我们通过这个协议来写一个韩国人  结构体

struct Korean: Human {
	var name: String = "Bob Lee"
	var race: String = "Asian"
	func sayHi() {
 		print("Hi, I'm \(name)")
 	}
}

一旦这个结构体采用了人类这个协议,它就必须”遵循”这个协议,实现它的所有属性和方法。如果不这么做的话, Xcode 会警报,当然左边也会报错  。

就像你看到的,为了满足蓝图你能够自定义所有的协议。你甚至可以建造一个“围墙”。

当然,对美国人  来说也是一样的。

struct American: Human {
 var name: String = "Joe Smith"
 var race: String = "White"
 func sayHi() { print("Hi, I'm \(name)") }
}

是不是相当酷?看看不再使用 “init” 和 “override” 关键词之后你拥有了多少自由。它是不是开始变得有点意思了?

协议介绍课程

协议继承

如果你想创建一个继承人类协议蓝图的超人协议该怎么办呢?

protocol SuperHuman: Human {
	var canFly: Bool { get set }
	func punch()
}

现在,如果你想生成一个采用超人协议的结构体或者类的话,你必须也要让它满足人类的协议。

//  超过 9000
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")
	}
}

那些理解不了的人,看下这个视频

当然,你可以像在类上面一样遵循多个协议。

// 例子
struct Example: ProtocolOne, ProtocolTwo { }

协议继承课程

协议扩展

现在,这是使用协议最强大的特点了,我不认为我需要讲太多。

// 会说英语的超级动物
protocol SuperAnimal {
	func speakEnglish()
}

给 SuperAnimal 增加一个扩展

extension SuperAnimal {
	func speakEnglish() {
		print("I speak English, pretty cool, huh?")
	}
}

现在,让我们来创建一个采用 SuperAnimal 协议的类。

class Donkey: SuperAnimal { }
var ramon = Donkey()
ramon.speakEnglish() //  "I speak English, pretty cool, huh?"

如果你使用扩展的话,你能够给类,结构体和枚举增加默认方法和属性。它难道不神奇么?我发现这是真正的金块啊。

顺带提一下,如果你没有理解的话,你可以看这个

Protocol Extension Lesson

协议作为类型 (Last)

如果我告诉你不需要类型修饰就能够生成一个既包含结构体对象又有类对象的数组呢?

就是这样。

我用为获得雌性配偶而打架的袋鼠来举个例子。如果你不相信我的话,看看这个袋鼠打架

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"

这个难道不巧妙么?你在面向对象编程中怎么可能实现这个效果... 封面的图片是不是对你来说已经有意义了?面向协议编程纯粹是金子啊。

协议类型课程

现在是免费的,直到它发布之前:)

最后提示

如果你觉得这个教程有用的话,而且你认为我做了一个很棒的事情,请  我并且分享到你的社交圈中。我发誓,更多的 iOS 开发者都该应该使用面向协议编程 !我也在努力中,所以才写了这个文章,但是为了更大的影响我需要你的支持。

公开感谢

特别感谢那些参与和指出各处问题的人们。Kilian Költzsch , Erik KrietschÖzgür Celebi , Sanchika Singh RanaFrederick C. Lee ,moh tabi , october hammer , Anthony Kersuzan , Kenneth Trueman , Wilson Balderrama , Rowin , Quang Dinh Luong , Oren Alalouf , Peter Witham , Victor Tong.

预告

这个周六,我将写一些关于在 Swift 3 中如何通过协议实现代理的设计模式的东西。有些人让我写这个,所以我决定听你们的。如果你想要快速更新或者请求我的文章的话,你可以关注我Facebook Page,那里我和我的读者有很多的互动。再见!





原文发布时间为:2017年2月3日


本文来自合作伙伴掘金,了解相关信息可以关注掘金网站。

时间: 2017-10-18

Swift 面向协议编程入门的相关文章

在 Swift 3 上对视图控件实践面向协议编程

本文讲的是在 Swift 3 上对视图控件实践面向协议编程, 学习如何对 button, label, imageView 创建动画而不制造一串乱七八糟的类 你可能听人说过,学到了知识却缺失了行动就好比人长了牙却还老盯着奶喝一样.那好,我们要怎样开始在我的应用中实践面向协议编程? 为了能更加高效的理解下面的内容,我希望读者能够明白 Complection Handlers,并且能创建协议的基本实现.如果你还不熟悉他们,可以先查看下面的文章和视频再回来接着看: 前景提要: Intro to Pro

Swift 中的面向协议编程是如何点亮我的人生的

本文讲的是Swift 中的面向协议编程是如何点亮我的人生的, 面向对象编程至今已经使用了数十年了,并且成为了构建大型软件约定俗成的标准.作为iOS编程的中心思想,遵循面向对象规范来编写一个 iOS 的应用几乎不可能实现.虽然面向对象有很多优点比如封装性,访问控制和抽象性,但是它也自带有固有的缺点. 大多数类的情况下,当一个单继承的类需要更多不同类中的函数功能时,你会倾向于使用多继承来实现. 但是大部分的编程语言不支持这一特性,而且会导致类的继承关系变得复杂. 在多线程环境下,如果所有对象在函数中

面向协议编程,灵丹妙药或是饮鸩止渴?

本文讲的是面向协议编程,灵丹妙药或是饮鸩止渴?, 在 Swift 中,面向协议编程正值流行.许多 Swift 框架都自称是面向协议编程的,一些开源库甚至将其标榜为特点.而我认为,很多时候眼下的问题本可以用一种更简单的方法解决,但是在 Swift 中我们过度使用各种协议了.简言之:不要教条地使用(或避免)协议. WWDC 2015(苹果电脑全球研发者大会,译者注)中最有影响力的一个分会场就是 Swift 中的面向协议编程.会议表明(当然还有其他内容)你能够用一个面向协议的解决方案替换掉类的层次结构

面向协议编程并非银弹

银弹(Silver Bullet)一词出自IBM大型机之父Frederick P. Brooks Jr.在1986年发表的一篇关于软件工程的经典论文<没有银弹:软件工程的本质性与附属性工作>(No Silver Bullet - Essence and Accidents of Software Engineering).其中的"银弹"是指一项可使软件工程的生产力在十年内提高十倍的技术或方法.该论文强调由于软件的复杂性本质,而使这样"真正的银弹"并不存在

C#面向服务编程技术WCF从入门到实战演练

  一.WCF课程介绍 1.1.Web Service会被WCF取代吗? 对于这个问题阿笨的回答是:两者在功能特性上却是有新旧之分,但是对于特定的系统,适合自己的就是最好的.不能哪一个技术框架和行业标准作比较,任何对于二者的比较都是错误的,因为两者根不不在同一个范畴里.就好比不能拿个汽车和交通法规比较一样,这是个误区. 阿笨的宗旨就是学完此<C#面向服务编程技术WCF从入门到实战演练>课程,让您从零基础上手后直接将学习的成果运用到实际项目中去.阿笨本次分享的WCF技术是完全来源于切身实际项目中

Swift的函数式编程详解_Swift

Swift 相比原先的 Objective-C 最重要的优点之一,就是对函数式编程提供了更好的支持. Swift 提供了更多的语法和一些新特性来增强函数式编程的能力,本文就在这方面进行一些讨论. Swift 概览 对编程语言有了一些经验的程序员,尤其是那些对多种不同类型的编程语言都有经验的开发者, 在学习新的语言的时候更加得心应手.原因在于编程语言本身也是有各种范式的, 把握住这些特点就可以比较容易的上手了. 在入手一门新的语言的时候,一般关注的内容有: 1.原生数据结构 2.运算符 3.分支控

面向服务编程

    从最初的面向过程编程,到后来觉得难以理解的面向对象编程,从软件工程的发展历程中来看,这已经成为我们编程路上熟知的两种编程方式.     接触了ITOO项目这么长时间,才发现,不知不觉,我们已经进入了软件工程发展历程之面向服务编程的开发.本篇博客的主题便是面向服务编程.     [一.面向服务编程从何而来?]     想要了解面向服务编程的发展方向以及它在软件行业中所占的地位,我们首先要了解的便是它的起源和发展.没有任何一种方法是一蹴而就的,应该是经历了数十年渐进的演化历程.下面,我们就来

ASP.NET编程入门随想之宽容(修改版)

asp.net|编程 相关文章:ASP.NET编程入门随想之宽容 古老的山谷村民生活富足,守旧老人维护着经典和秩序.一位不满现状的漂泊者却宣称外面有更好的世界在等着大家,并鼓动村民跟随前往.但守旧老人的威严和律法的神圣压制了村民的躁动,漂泊者也被处死.一天灾难降临山谷.尽管守旧老人依然试图维护经受村民的求生欲望挑战的律法.但暴动还是发生,老人们被击败,新的道路和新的生活被村民找到.怀着感恩之心,后人把以前的漂泊者奉为先知,尽管他早已尸骨无存. -- 房龙<宽容•序言> ■ 宽容 – W3C 的

AOP编程入门--Java篇

编程 Aspect Oriented Programming(AOP),面向切面编程,是一个比较热门的话题.AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果.比如我们最常见的就是日志记录了,举个例子,我们现在提供一个服务查询学生信息的,但是我们希望记录有谁进行了这个查询.如果按照传统的OOP的实现的话,那我们实现了一个查询学生信息的服务接口(StudentInfoService)和其实现类(Student