协议 #

一、协议概述 #

协议定义了适合特定任务的属性、方法和下标的蓝图,可以被类、结构体和枚举采纳。

1.1 协议特点 #

  • 定义接口规范
  • 支持多协议采纳
  • 支持协议继承
  • 支持协议扩展

二、定义协议 #

2.1 基本语法 #

swift
protocol Drawable {
    func draw()
    var area: Double { get }
}

class Circle: Drawable {
    var radius: Double
    
    init(radius: Double) {
        self.radius = radius
    }
    
    func draw() {
        print("画圆")
    }
    
    var area: Double {
        return Double.pi * radius * radius
    }
}

2.2 属性要求 #

swift
protocol Named {
    var name: String { get set }
    var id: Int { get }
}

struct Person: Named {
    var name: String
    let id: Int
}

var person = Person(name: "张三", id: 1)
print(person.name)

2.3 方法要求 #

swift
protocol Greetable {
    func greet(name: String) -> String
}

class Greeter: Greetable {
    func greet(name: String) -> String {
        return "Hello, \(name)!"
    }
}

let greeter = Greeter()
print(greeter.greet(name: "Swift"))

2.4 可变方法要求 #

swift
protocol Toggleable {
    mutating func toggle()
}

enum Switch: Toggleable {
    case on, off
    
    mutating func toggle() {
        switch self {
        case .on:
            self = .off
        case .off:
            self = .on
        }
    }
}

var lightSwitch = Switch.off
lightSwitch.toggle()
print(lightSwitch)

三、协议扩展 #

3.1 默认实现 #

swift
protocol Greetable {
    func greet() -> String
}

extension Greetable {
    func greet() -> String {
        return "Hello!"
    }
}

struct Person: Greetable {
    var name: String
}

let person = Person(name: "张三")
print(person.greet())

3.2 添加约束 #

swift
extension Collection where Element: Numeric {
    func sum() -> Element {
        return reduce(0, +)
    }
}

let numbers = [1, 2, 3, 4, 5]
print(numbers.sum())

3.3 协议组合 #

swift
protocol Named {
    var name: String { get }
}

protocol Aged {
    var age: Int { get }
}

func wishHappyBirthday(to celebrator: Named & Aged) {
    print("生日快乐, \(celebrator.name), 你\(celebrator.age)岁了!")
}

struct Person: Named, Aged {
    var name: String
    var age: Int
}

let person = Person(name: "张三", age: 25)
wishHappyBirthday(to: person)

四、协议继承 #

4.1 基本继承 #

swift
protocol Animal {
    var name: String { get }
    func speak()
}

protocol Pet: Animal {
    var owner: String { get }
}

class Dog: Pet {
    var name: String
    var owner: String
    
    init(name: String, owner: String) {
        self.name = name
        self.owner = owner
    }
    
    func speak() {
        print("汪汪")
    }
}

4.2 类专用协议 #

swift
protocol ClassOnly: AnyObject {
    func doSomething()
}

class MyClass: ClassOnly {
    func doSomething() {
        print("执行操作")
    }
}

五、关联类型 #

5.1 基本用法 #

swift
protocol Container {
    associatedtype Item
    var count: Int { get }
    mutating func append(_ item: Item)
    subscript(i: Int) -> Item { get }
}

struct IntStack: Container {
    var items: [Int] = []
    
    var count: Int {
        return items.count
    }
    
    mutating func append(_ item: Int) {
        items.append(item)
    }
    
    subscript(i: Int) -> Int {
        return items[i]
    }
}

5.2 类型约束 #

swift
protocol Container {
    associatedtype Item: Equatable
    var count: Int { get }
    mutating func append(_ item: Item)
    subscript(i: Int) -> Item { get }
}

六、协议作为类型 #

6.1 协议类型 #

swift
protocol Drawable {
    func draw()
}

class Circle: Drawable {
    func draw() { print("画圆") }
}

class Square: Drawable {
    func draw() { print("画方") }
}

let shapes: [Drawable] = [Circle(), Square()]
shapes.forEach { $0.draw() }

6.2 委托模式 #

swift
protocol DownloadDelegate: AnyObject {
    func downloadDidFinish(data: Data)
    func downloadDidFail(error: Error)
}

class Downloader {
    weak var delegate: DownloadDelegate?
    
    func download(url: URL) {
        DispatchQueue.global().async {
            Thread.sleep(forTimeInterval: 1)
            DispatchQueue.main.async {
                self.delegate?.downloadDidFinish(data: Data())
            }
        }
    }
}

class ViewController: DownloadDelegate {
    func downloadDidFinish(data: Data) {
        print("下载完成")
    }
    
    func downloadDidFail(error: Error) {
        print("下载失败")
    }
}

七、实际应用 #

7.1 网络请求协议 #

swift
protocol APIRequest {
    associatedtype Response: Decodable
    var path: String { get }
    var method: String { get }
    var parameters: [String: Any]? { get }
}

extension APIRequest {
    var method: String { return "GET" }
    var parameters: [String: Any]? { return nil }
}

struct UserRequest: APIRequest {
    typealias Response = User
    let path: String
    
    init(userId: Int) {
        self.path = "/users/\(userId)"
    }
}

7.2 构建器协议 #

swift
protocol Builder {
    associatedtype Product
    func build() -> Product
}

class URLBuilder: Builder {
    private var components = URLComponents()
    
    func setScheme(_ scheme: String) -> URLBuilder {
        components.scheme = scheme
        return self
    }
    
    func setHost(_ host: String) -> URLBuilder {
        components.host = host
        return self
    }
    
    func setPath(_ path: String) -> URLBuilder {
        components.path = path
        return self
    }
    
    func build() -> URL? {
        return components.url
    }
}

let url = URLBuilder()
    .setScheme("https")
    .setHost("api.example.com")
    .setPath("/users")
    .build()

7.3 策略模式 #

swift
protocol SortStrategy {
    func sort<T: Comparable>(_ array: [T]) -> [T]
}

struct AscendingSort: SortStrategy {
    func sort<T: Comparable>(_ array: [T]) -> [T] {
        return array.sorted()
    }
}

struct DescendingSort: SortStrategy {
    func sort<T: Comparable>(_ array: [T]) -> [T] {
        return array.sorted(by: >)
    }
}

class Sorter {
    private var strategy: SortStrategy
    
    init(strategy: SortStrategy) {
        self.strategy = strategy
    }
    
    func sort<T: Comparable>(_ array: [T]) -> [T] {
        return strategy.sort(array)
    }
}

八、总结 #

本章学习了Swift协议:

  • 协议定义:属性和方法要求
  • 协议扩展:默认实现
  • 协议继承:继承其他协议
  • 关联类型:泛型协议

最佳实践:

  • 面向协议编程
  • 使用协议扩展提供默认实现
  • 使用委托模式解耦
  • 合理使用关联类型

下一章,我们将学习扩展!

最后更新:2026-03-26