Tailwind CSSTailwind CSS
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain

第2章:Swift 协议的基础

2.5 协议的实现:结构体、类和枚举

Swift 的协议之所以强大,不仅在于其定义行为的灵活性,还在于它能够被多种类型遵循,包括结构体(Struct)、类(Class)和枚举(Enum)。这种多类型支持是协议化编程(POP)区别于传统面向对象编程(OOP)的重要特性,允许开发者根据需求选择最合适的类型来实现协议。本节将探讨结构体、类和枚举如何遵循协议,分析它们的差异,并通过示例展示其在实际开发中的应用。

协议的多类型支持

Swift 的协议是类型无关的,它只定义行为要求,不限制遵循者的具体类型。这意味着结构体、类和枚举都可以通过 : 符号遵循协议并实现其要求。例如:

protocol Displayable {
    var displayName: String { get }
    func show()
}

接下来,我们将分别用结构体、类和枚举实现这个协议,展示它们的特点。

1. 结构体实现协议

结构体是 Swift 中的值类型,具有不可变性和线程安全的特性,非常适合用于数据建模或无副作用的场景。结构体实现协议时,需要注意修改自身状态时使用 mutating 关键字。例如:

struct Product: Displayable {
    var displayName: String
    var isVisible: Bool
    
    func show() {
        if isVisible {
            print("Showing: \(displayName)")
        } else {
            print("\(displayName) is hidden")
        }
    }
}

var product = Product(displayName: "Laptop", isVisible: true)
product.show() // 输出: Showing: Laptop
  • 特点:值语义,复制时生成独立副本,避免引用共享问题。
  • 适用场景:数据模型、不可变状态或轻量级对象。

如果需要修改结构体状态,可以添加 mutating 方法:

protocol Adjustable {
    mutating func adjust()
}

struct Counter: Adjustable {
    var count: Int
    
    mutating func adjust() {
        count += 1
    }
}

var counter = Counter(count: 0)
counter.adjust()
print(counter.count) // 输出: 1

2. 类实现协议

类是引用类型,适合需要共享状态或复杂继承关系的场景。类实现协议时无需 mutating,但需要注意初始化器要求和继承相关的问题。例如:

class Vehicle: Displayable {
    var displayName: String
    
    init(displayName: String) {
        self.displayName = displayName
    }
    
    func show() {
        print("Vehicle: \(displayName)")
    }
}

let vehicle = Vehicle(displayName: "Car")
vehicle.show() // 输出: Vehicle: Car

如果协议要求初始化器,类需要使用 required(非 final 类)或确保完全实现:

protocol Configurable {
    init(config: String)
}

class Gadget: Configurable {
    var config: String
    
    required init(config: String) {
        self.config = config
    }
}
  • 特点:引用语义,适合共享状态,支持继承。
  • 适用场景:需要对象生命周期管理或与 Objective-C 交互的场景(如 UIKit)。

3. 枚举实现协议

枚举是值类型,通常用于定义有限状态集或选项。枚举实现协议时,可以结合模式匹配和关联值,提供独特的实现方式。例如:

enum Status: Displayable {
    case active(String)
    case inactive
    
    var displayName: String {
        switch self {
        case .active(let name):
            return name
        case .inactive:
            return "Inactive"
        }
    }
    
    func show() {
        print("Status: \(displayName)")
    }
}

let activeStatus = Status.active("Running")
activeStatus.show() // 输出: Status: Running

let inactiveStatus = Status.inactive
inactiveStatus.show() // 输出: Status: Inactive
  • 特点:值语义,适合有限状态或类型安全的场景。
  • 适用场景:状态机、选项集或需要模式匹配的逻辑。

三者的对比

类型语义继承性修改性典型场景
结构体值语义无继承需要 mutating数据模型、不可变对象
类引用语义支持继承无需 mutating共享状态、复杂对象
枚举值语义无继承需要 mutating状态机、选项定义

实际应用示例

假设我们要设计一个表示“任务”的系统,可以用不同类型实现相同的协议:

protocol Task {
    var title: String { get }
    func execute()
}

struct SimpleTask: Task {
    var title: String
    
    func execute() {
        print("Executing simple task: \(title)")
    }
}

class ComplexTask: Task {
    var title: String
    var subtasks: [Task]
    
    init(title: String, subtasks: [Task] = []) {
        self.title = title
        self.subtasks = subtasks
    }
    
    func execute() {
        print("Executing complex task: \(title)")
        subtasks.forEach { $0.execute() }
    }
}

enum TaskState: Task {
    case pending(String)
    case completed(String)
    
    var title: String {
        switch self {
        case .pending(let t), .completed(let t):
            return t
        }
    }
    
    func execute() {
        switch self {
        case .pending:
            print("Pending task: \(title)")
        case .completed:
            print("Completed task: \(title)")
        }
    }
}

let simple = SimpleTask(title: "Write code")
let complex = ComplexTask(title: "Build app", subtasks: [simple])
let state = TaskState.pending("Test app")

simple.execute()  // 输出: Executing simple task: Write code
complex.execute() // 输出: Executing complex task: Build app
                  //       Executing simple task: Write code
state.execute()   // 输出: Pending task: Test app
  • SimpleTask 用结构体实现简单任务。
  • ComplexTask 用类实现支持子任务的复杂任务。
  • TaskState 用枚举实现任务状态。

注意事项

  1. 选择类型:根据需求选择合适的类型,例如需要值语义时优先结构体,需要继承时使用类。
  2. 性能考虑:结构体和枚举通常有静态分派优势,而类的动态分派可能有额外开销。
  3. 一致性:无论类型如何,所有遵循者必须满足协议的完整要求。

小结

结构体、类和枚举为协议的实现提供了多样化的选择,体现了 Swift POP 的灵活性。结构体适合轻量数据建模,类适合复杂对象管理,枚举适合状态表示。理解这些类型的特点,可以帮助开发者在不同场景中做出最佳设计决策。下一节将通过实战案例,展示如何用协议实现简单的模型层。


Last Updated:: 3/9/25, 2:18 PM