一: 面向协议编程
面向协议编程(Protocol Oriented Programming,简称POP)
1 是Swift的一种编程范式, Apple于2015年WWDC提出
在Swift的标准库中,能见到大量POP的影子
2 同时,Swift也是一门面向对象的编程语言(Object Oriented Programming,简称OOP)
3 在Swift开发中,OOP和POP是相辅相成的,任何一方并不能取代另一方
4 POP 能弥补OOP (面向对象) 一些设计上的不足-
回顾OOP
OOP的三大特性:封装、继承、多态
继承的经典使用场合
当多个类(比如A、B、C类)具有很多共性时,可以将这些共性抽取到一个父类中(比如D类),最后A、B、C类继D类
-
回顾OOP不足
POP的解决方案
protocol Runnable { // 声明协议
func run()
}
extension Runnable { // 扩展实现协议, 否则继承类需要自己实现
func run() {
print("run")
}
}
class BVC: UIViewController, Runnable {}
class DVC: UITableViewController, Runnable {}
// 通过类继承协议, 从而获取协议方法, run
-
POP的注意点
优先考虑创建协议,而不是父类(基类)
优先考虑值类型(struct、enum),而不是引用类型(class) n 巧用协议的扩展功能
不要为了面向协议而使用
二: 利用协议实现前缀效果
封装方法 -- 获取字符串内, 数字的个数
struct MJ<Base> {
let base: Base
init(_ base: Base) {
self.base = base
}
}
protocol MJCompatible {}
extension MJCompatible {
static var mj: MJ<Self>.Type { // 协议包含静态 mj 计算属性
get {
MJ<Self>.self // 获取当前类
}
set {}
}
var mj: MJ<Self> { // 协议包含 mj 计算属性
get {
MJ(self) // 获取当前对象
}
set {}
}
}
// self: Person.self 代表原类型, self.age获取对象属性
// Self: 代表当前类 Self.count 代表类属性
// 给 MJ 结构体添加numberCount方法, 限制泛型必须是 String类型
extension MJ where Base == String {
// 注意 == String 代表 Base 只能是字符串, Base: Car 代表 Base 继承或是其子类
// 新增 numberCount方法, 获取int数
func numberCount() -> Int {
var count = 0
for c in base where ("0"..."9").contains(c) {
count += 1
}
return count
}
// 新增 属性, 获取int数
var numCount: Int {
var count = 0
for c in base where ("0"..."9").contains(c) {
count += 1
}
return count
}
}
extension String: MJCompatible {}
let string = "123fdsf434"
print(string.mj.numberCount()) // 6
print(string.mj.numberCount) // 6
// 遵守协议, 获得协议属性 mj
// 添加MJ分类, 获得 numberCount 方法, 并限制String类型调用
三: 利用协议实现类型判断
1 通过对象判断类型
// 1 判断value是否为数组
func isArray(_ value: Any) -> Bool {
value is [Any]
}
isArray( [1, 2] ) // true
isArray( ["1", 2] ) // true
isArray( NSArray() ) // true
isArray( NSMutableArray() ) // true
** 通过传入类型判断类型 (这样不行 XXX)**
func isArrayType(_ type: Any.Type) -> Bool {
type is [Any].Type
}
print(isArrayType([Int].self)) //false
print(isArrayType([Any].self)) //true
print(isArrayType(NSArray.self)) //false
print(isArrayType(NSMutableArray.self)) //false
// [Any].Type不等于 [Int].self类型
2 通过传入类型判断类型 (这样可以~~~)
// Array NSArray 遵守协议
protocol ArrayType {}
extension Array: ArrayType {}
extension NSArray: ArrayType{}
func isArrayType(_ type: Any.Type) -> Bool {
type is ArrayType.Type
}
print(isArrayType([Int].self)) //true
print(isArrayType([Any].self)) //true
print(isArrayType(NSArray.self)) //true
print(isArrayType(NSMutableArray.self)) //true