协议
协议定义了一组方法、属性或其他要求,用于指定 遵循该协议的类型 所需实现的功能。
协议可以声明:方法、属性、下标
可以被结构体、类、枚举遵守,多个协议之间用逗号隔开。
1.声明协议
关键字
protocol
protocol SomeProtocol {
var id: Int { get set }
var token: String { get }
func someMethod()
init(parameter: String)
}
在协议内部,列出所需的所有方法,这些方法内部不包含具体实现。
定义 类型方法、类型属性、类型下标,必须用static
- 协议属性
协议中定义属性时,必须用var
实现协议时的属性权限,要不小于协议中定义的属性权限
协议定义get、set,用var存储属性或get、set计算属性去实现
协议定义get,用任何属性都可以实现
- 初始化器
协议的init
协议中还可以定义 init。非final类实现时必须加上required
protocol Drawable {
init(x: Int, y: Int)
}
class Point : Drawable {
required init(x: Int, y: Int) { }
}
final class Size : Drawable {
init(x: Int, y: Int) { }
}
如果从协议实现的初始化器,刚好是重写了父类的指定初始化器,那么这个初始化必须同时加required、override。
// 协议
protocol Livable {
init(age: Int)
}
// 父类
class Person {
init(age: Int) { }
}
class Student : Person, Livable {
required override init(age: Int) {
super.init(age: age)
}
}
- init、init?、init!
协议中定义的
init?、init!,可以用init、init?、init!去实现。 协议中定义的init,可以用init、init!去实现
protocol Livable {
init()
init?(age: Int)
init!(no: Int)
}
class Person : Livable {
required init() { }
// required init!() { }
required init?(age: Int) { }
// required init!(age: Int) { }
// required init(age: Int) { }
required init!(no: Int) { }
// required init?(no: Int) { }
// required init(no: Int) { }
}
2.遵守协议
结构体、类或枚举,都可以遵守协议,来实现该协议的所有方法。
struct MyStruct: SomeProtocol {
var someProperty: Int
func someMethod() {
print("Implemented")
}
init(someParameter: String) {
self.someProperty = someParameter.count
}
}
协议一般没有指定 类型的全部功能,仅指定了最低限度的功能。您可以根据需要为类型添加其他属性和方法。
遵守协议的类、结构体或枚举,必须实现协议方法的 具体内容
那么,协议有什么特殊作用?——它允许我们使用 协议 作为参数的类型。
func printInfo(_ value: SomeProtocol) {
value.someMethod()
}
因此,协议让我们只关注我们想要使用的功能类型,而不关注确切的类型。
3.为什么 Swift 需要协议?
协议可以让我们定义 结构体、类和枚举应该如何工作:应该具有什么方法、属性。
Swift 将为我们强制执行这些规则,因此,当我们说某个类型符合协议时,Swift 将确保它一定具有该协议所需的所有方法和属性。
在实践中,协议允许我们以更通用的方式 处理我们的数据。
4.协议的继承
协议可以继承其他协议,实现功能的叠加。
5.协议合成 &
protocol A { }
protocol B { }
func printIt(value: A & B) { }
表示传入的值必须同时遵守协议 A 和 B。
6.类限定协议
使用 AnyObject 限定只有类 能遵守此协议,常用于 delegate 模式。
protocol MyDelegate: AnyObject {
func didSomething()
}
7.可选协议方法
只能被 class 遵守,只能用于 @objc 的协议(兼容 Objective-C)
@objc protocol MyObjCDelegate {
@objc optional func optionalMethod()
}
协议扩展
Swift 允许为协议提供默认实现,通过 extension 扩展协议。这是 Swift 面向协议编程(POP)的核心特性。
协议中定义方法时,不能有默认参数值。 默认情况下,协议中定义的内容必须全部都实现
用途:
- 提供默认实现
这让我们不需要在许多结构和类之间,复制该功能。
- 添加通用方法(即使协议没有声明)
- 避免重复代码
- 构建功能模块
protocol Greetable {
func greet()
}
extension Greetable {
func greet() {
print("Hello!")
}
}
这样,遵循者即使没有实现协议方法,也能直接调用。若遵循者实现了需要方法,则会覆盖。
类扩展 只影响某个具体类型; 协议扩展 影响所有遵循该协议的类型
使用场景
-
委托模式
-
数据源模式(DataSource)
-
ViewModel/Service 通用接口
-
泛型+协议约束组合
func printAll<T: CustomStringConvertible>(_ items: [T]) {
for item in items {
print(item.description)
}
}