Swift面向协议编程
所谓面向协议编程,就是使用protocol
声明方法,然后使用extension
提供默认的实现,只要需要使用到该方法的类遵循该protocol
,就可以直接使用该extension
的实现。
1 | protocol animal { |
代码复用
- 继承:会带来耦合。
- 继承的代价:这并不是一个新颖的话题,自面向对象编程诞生之日起就饱受争议,我们经常要忍受着愈加繁杂和庞大的继承体系来获得代码的可重用性,而且随着继承层次的增加,代码的复杂性会加速增长,随之而来的bug也会越来越难以发现。这时我们可能需要依靠设计模式来找回我们的思路,然而大多数设计模式只能帮助你理顺你的代码结构,却在同时更加加深了你的代码的复杂度。
category
/extension
:会污染所有的类- 面向协议编程:
protocol
+extension
最大程度地减少了耦合
面向协议编程的好处
面向协议编程的好处在于,通过协议+扩展实现一个功能,能够定义所需要的充分必要条件,不多也不少。这样就最大程度减少了耦合。使用者可以像搭积木一样随意组合这些协议,写一个class
或struct
来完成复杂的功能。实际上,Swift的标准库几乎是everything is starting out as a protocol
。
- 代码没有增多,却更复⽤
- ⾯向协议(接⼝),⽽不是实现,充分解耦
- 静态类型检查帮助在编译时发现问题
- 写代码像搭积木,先设计接⼝,再逐⼀实现
- 依赖少,更容易调试
为什么说Swift是面向协议编程的语言?
因为Swift
里更推荐使用值类型变量(struct
)而不是引用类型(class
)的变量,Swift
中许多常见的数据类型、字符串、集合类型,以及结构体和枚举都是值类型而非引用类型,值类型的变量在赋值时会自动进行一次低消耗的值拷贝,对比对象的copy
要更加高效而且不存在线程安全问题。
为什么需要struct
struct
和class
的主要区别:
struct
是值类型,而class
是引用类型struct
没有继承的功能,class
有继承功能
struct和class这两个基本层面的区别,体现了区别于Objective-C语言,swift语言带来了全新的天翻地覆的改变。
首先说第一点区别,从swift
的更新和struct
不断完善来看,苹果公司更加推荐使用struct
来代替class
,因为struct
值类型和class
引用类型这点区别,保证使用struct
编码能写出更加安全可靠的代码。为什么这样说呢,class
引用类型在赋值时是将变量指向了同一块内存地址,这在一个长时间的跨度上会带来一些意想不到的问题,试想一个简单的例子,viewControllerA
持有一个NSMutableArray
数组mutalbeArray
,它包含100条user
信息,此时将mutableArray
赋值给viewControllerB
,对于viewControllerB
而言,它仅仅需要前10条user
信息,所以它将mutableArray
多余的信息删除了,这样一个脑残的操作导致了viewControllerA
模块展示错误和潜在的逻辑错误。而使用struct
值引用则不会出现这样的问题。
第二点区别,struct
没有继承的功能,这是因为swift
在本质上来说是面向协议(Protocol Oriented
)的语言,struct
没有也不需要继承的功能,为了实现某个功能,struct
去服从并实现某个协议就即可,从一个较高的层次来看,struct+protocol
是构成swift
面向协议语言的两个基石。
Swift标准库
在 Swift 标准库里,包含55个 Protocol,102个 Struct,9个 Enums 和6个 Class,由此可见,苹果更推荐使用 Struct。
55个 Protocol 中大致可以分为三种类型:
- -Type:
- BooleanType
- CollectionType
- ErrorType
- -able:
- Comparable
- Equatable
- Hashable
- -Convertible
- ArrayLiteralConvertible
- BooleanLiteralConvertible
- CustomDebugStringConvertible
协议的两种类型
普通的协议可以被当作类型约束使用,也可以当作独立的类型使用。带有关联类型或者 Self 约束的协议特殊一些:我们不能将它当作独立的类型来使用,而只能将它们用作类型约束。
总结
Swift是一门支持多编程范式的语言,既支持面向对象编程,也支持面向协议编程,同时还支持函数式编程。在项目开发过程中,控制器和视图部分由于使用系统框架,应更多采用面向对象编程的方式;而模型或业务逻辑等自定义类型部分,则应优先考虑面向协议编程。