Swift 协议(Protocol)详解
在 Swift 中,协议(Protocol) 是一种定义行为契约的机制。它不实现功能,只声明方法、属性、下标等要求,任何类型(类、结构体、枚举)只要符合协议,就必须实现这些要求。
1. 基本语法
protocol SomeProtocol {
// 协议内容
var property: Int { get set } // 可读可写属性
func method(param: String) -> Bool // 必须实现的方法
static func staticMethod() // 静态方法
}
2. 采用协议(Conformance)
struct MyStruct: SomeProtocol {
var property: Int // 必须实现
func method(param: String) -> Bool { // 必须实现
return param.count > 5
}
static func staticMethod() { // 必须实现
print("Static method")
}
}
3. 协议作为类型使用
协议可以像其他类型一样使用:
func process(item: SomeProtocol) {
print(item.property)
}
let obj = MyStruct(property: 10)
process(item: obj) // 多态
4. 属性要求
protocol FullyNamed {
var fullName: String { get } // 至少可读
var nickname: String { get set } // 可读可写
}
注意:协议只关心 get/set 能力,不关心是
var还是计算属性。
struct Person: FullyNamed {
var fullName: String { "John Doe" } // 计算属性(只读)
var nickname: String = "JD" // 存储属性
}
5. 方法要求
protocol Randomizable {
mutating func randomize() // 可变方法(用于 struct/enum)
static func defaultValue() -> Self // 类型方法
}
类中不需要
mutating,因为类是引用类型。
6. 初始化器要求
protocol Initializable {
init(value: Int)
}
struct Counter: Initializable {
var count: Int
init(value: Int) {
self.count = value
}
}
类采用协议时,若协议要求初始化器,需加
required:
class MyClass: Initializable {
required init(value: Int) { ... }
}
7. 协议继承
protocol Named {
var name: String { get }
}
protocol Aged {
var age: Int { get }
}
protocol PersonProtocol: Named, Aged { // 继承多个协议
func introduce()
}
8. 协议组合(Protocol Composition)
func wishHappyBirthday(to person: Named & Aged) {
print("Happy birthday \(person.name), you're \(person.age)!")
}
let john = Person(name: "John", age: 30)
wishHappyBirthday(to: john) // 同时满足 Named 和 Aged
9. 协议扩展(Protocol Extension)
为协议提供默认实现:
protocol Greetable {
var name: String { get }
func greet()
}
extension Greetable {
func greet() {
print("Hello, \(name)!")
}
}
struct User: Greetable {
var name: String
}
// User 自动获得 greet() 实现
let user = User(name: "Alice")
user.greet() // 输出: Hello, Alice!
可通过扩展为协议添加新功能,甚至条件扩展:
extension Greetable where Self: Equatable {
func isSame(as other: Self) -> Bool {
return self == other
}
}
10. 常用系统协议
| 协议 | 作用 |
|---|---|
Equatable | 支持 == 比较 |
Hashable | 可作为 Dictionary 键 |
Comparable | 支持 < > <= >= |
Codable | 自动编码/解码 JSON |
Identifiable | SwiftUI 中标识唯一对象 |
CaseIterable | 枚举自动生成 allCases |
示例:
struct Point: Equatable, Codable {
var x: Int
var y: Int
}
11. 协议与类专属(class-only)
使用 AnyObject 限制仅类可采用:
protocol Delegate: AnyObject {
func didFinish()
}
class MyViewController {
weak var delegate: (any Delegate)? // Swift 5.7+ 写法
}
Swift 5.7+ 推荐使用
any Delegate,旧写法Delegate?
12. 存在类型(Existential)与 any
let items: [any Greetable] = [User(name: "A"), Person(name: "B")]
any Protocol表示“某个符合该协议的类型”,用于泛型擦除场景。
小结:协议的核心价值
| 特性 | 说明 |
|---|---|
| 抽象行为 | 定义“做什么”,不关心“怎么做” |
| 多态 | 不同类型统一接口 |
| 默认实现 | 通过扩展减少重复代码 |
| 组合灵活 | 协议组合、继承、条件扩展 |
| 面向协议编程(POP) | Swift 推荐的编程范式 |
推荐实践
// 优先使用协议而非继承
protocol Payable { func pay() }
extension Payable { func pay() { print("Paid") } }
// 多个小协议优于一个大协议
protocol Walkable { func walk() }
protocol Swimmable { func swim() }
需要代码示例项目?还是想看 协议与泛型结合、POP 设计模式?欢迎继续提问!