WWDC 学习笔记 —— Swift 中的面向协议编程

WWDC 2015 - Session 408 - iOS, OS X, watchOS

本文核心基于 WWDC 主题演讲内容,结合我自己的一些想法,大家可以当成翻译看。

WWDC 学习笔记 —— Swift 中的面向协议编程_第1张图片
WWDC 2015

Back to then

假设我们要设计一个画板应用,核心的模块应该是可绘制对象渲染引擎,我分别称它们为Drawable, Renderer。我们知道所有可绘制对象都应该有一个方法来执行绘制操作,也就是说不管矩形、圆形还是其他图形都应该有一个可以统一调用的 render,于是很容易想到的就是声明一个抽象类,里面有一个未实现的 render 函数,但是这里我并不想使用 class,而是使用 struct,为什么呢?因为图形都是由基本值类型构成的,而且功能比较单一。有关于引用类型和值类型的最佳实践我会再开一篇文章来写(同样也是 WWDC 的内容)。

首先我们写一个矩形类型:


WWDC 学习笔记 —— Swift 中的面向协议编程_第2张图片
Figure. 1

下面我们设计渲染类,为了方便测试图形绘图的行为,我们先写一个“假的”渲染器,来向控制台输出调试语句:


WWDC 学习笔记 —— Swift 中的面向协议编程_第3张图片
Figure. 2

但是我会说,这是个很差的设计,它很难被重构、扩展、推广。如果我想用 CoreGraphics 渲染怎么办?用 QuartzCore 呢?以后推广到 X Server 呢(虽然有点扯)?逐一重写?

Now, let's Protocol-Oriented Programming

回到标题,还是用协议,统一所有的接口方法:


Figure. 3

那么上面的测试渲染器就可以遵守这个协议来写实现了:


WWDC 学习笔记 —— Swift 中的面向协议编程_第4张图片
Figure. 4

下面介绍一下 extension 在协议方面的应用,现在我们来写基于 CoreGraphics 的实现,也就是实现一个渲染器,它可以操作 CGContext 来画图,继承 CGContext?为什么不扩展它呢?

WWDC 学习笔记 —— Swift 中的面向协议编程_第5张图片
Figure. 5

通过 extension 关键字我们可以将一个现有的类扩展到遵守一个协议。随手写一个 UIView 来显示绘制内容,这里就不解释了。

下面测试一下吧!


WWDC 学习笔记 —— Swift 中的面向协议编程_第6张图片
Figure. 6

Hold on

下面我们再写一个圆形类和组合类吧。组合类没什么好说的,说说圆形类。
圆形类型的定义我这么写的:


WWDC 学习笔记 —— Swift 中的面向协议编程_第7张图片
Figure. 7

然后看看结果:


WWDC 学习笔记 —— Swift 中的面向协议编程_第8张图片
Figure. 8

诶,什么鬼?怎么有条线啊....
因为 lineTo 完毕后起点在矩形左上角,再画弧 (arcTo) 就会顺带拉一条线出来...

所以我要先用 moveTo 把起点移到圆形右边,难道以后画任何圆都要先来这么一下??我觉得渲染器应该帮我做这件事啊喂!简单分析可以发现,这个组合动作用协议现有的方法完全可以做到,我们不必去在原有的 Renderer 协议中加一个 circleAt 方法,然后在各个渲染器实现中逐一实现一遍这个重复的组合操作。

这里我们可以用协议扩展,没错,就是这么写:


Figure. 9

然后圆形类就可以直接调用渲染器的 circleAt 方法来画圆了。

最后的代码:


WWDC 学习笔记 —— Swift 中的面向协议编程_第9张图片
Figure. 10

这就是面向协议编程了,当然还有一部分内容本文没有涉及,我会在以后更新这部分内容和"值类型的最佳实践"两篇文章。就是这样!

你可能感兴趣的:(WWDC 学习笔记 —— Swift 中的面向协议编程)