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.2 属性要求(Property Requirements)

在 Swift 的协议中,属性要求是定义类型必须具备的属性的一种方式。通过属性要求,协议可以指定遵循者需要提供哪些数据接口,以及这些属性的读写权限。属性要求是协议化编程(POP)的核心组成部分之一,它为类型提供了一致的访问方式,同时保持了实现的灵活性。本节将详细探讨属性要求的语法、使用场景和注意事项,并通过示例展示其实际应用。

属性要求的语法

协议中的属性要求使用熟悉的属性声明语法,但不包含具体实现,只需指定名称、类型和访问权限(get 或 get set)。基本形式如下:

protocol ProtocolName {
    var propertyName: Type { get }       // 只读属性
    var anotherProperty: Type { get set } // 可读写属性
}
  • { get }:表示属性必须可读,遵循者可以选择提供存储属性或计算属性的只读实现。
  • { get set }:表示属性必须可读写,遵循者需要提供可读写的实现,通常通过变量(var)实现。

例如:

protocol Identifiable {
    var id: String { get }
    var isActive: Bool { get set }
}

在这里,id 是只读属性,isActive 是可读写属性。

实现属性要求

遵循协议的类型必须满足属性要求,可以通过存储属性或计算属性实现。例如:

struct User: Identifiable {
    let id: String          // 只读存储属性
    var isActive: Bool      // 可读写存储属性
}

class Account: Identifiable {
    var id: String {        // 只读计算属性
        return UUID().uuidString
    }
    var isActive: Bool      // 可读写存储属性
}
  • User 使用存储属性(let 和 var)实现要求,id 是不可变的,isActive 是可变的。
  • Account 使用计算属性实现 id,每次访问时生成一个新的 UUID,同时用存储属性实现 isActive。

这种灵活性让遵循者可以根据需求选择最适合的实现方式。

只读与可读写的区别

属性要求的读写权限直接影响遵循者的实现:

  • 只读属性({ get }):遵循者可以提供存储属性(let 或 var)、只读计算属性,甚至是带有 private set 的属性,只要外部可读即可。
  • 可读写属性({ get set }):遵循者必须提供外部可读写的属性,通常是 var 存储属性或带有 get 和 set 的计算属性。

例如:

protocol Adjustable {
    var level: Int { get set }
}

struct Volume: Adjustable {
    var level: Int          // 直接使用存储属性
    
    init(level: Int) {
        self.level = level
    }
}

struct Brightness: Adjustable {
    private var _level: Int // 私有存储
    var level: Int {        // 计算属性实现可读写
        get { _level }
        set { _level = max(0, min(100, newValue)) }
    }
    
    init(level: Int) {
        self._level = level
    }
}

Volume 使用简单的存储属性,而 Brightness 通过计算属性限制 level 的范围(0 到 100),两种方式都满足了 get set 要求。

静态属性要求

协议不仅可以定义实例属性,还可以定义静态属性(类型属性),使用 static 关键字。例如:

protocol Categorizable {
    static var category: String { get }
}

struct Book: Categorizable {
    static var category: String = "Literature"
}

print(Book.category) // 输出: Literature

静态属性要求常用于定义与类型本身相关的属性,而不是实例特定的数据。

属性要求的实际应用

属性要求在建模和抽象中非常有用。例如,假设我们要设计一个表示“形状”的协议:

protocol Shape {
    var area: Double { get }        // 只读,表示面积
    var isVisible: Bool { get set } // 可读写,表示可见性
}

struct Circle: Shape {
    let radius: Double
    var isVisible: Bool
    
    var area: Double {
        return Double.pi * radius * radius
    }
}

struct Rectangle: Shape {
    let width: Double
    let height: Double
    var isVisible: Bool
    
    var area: Double {
        return width * height
    }
}

var circle = Circle(radius: 5, isVisible: true)
print(circle.area)       // 输出: 78.53981633974483
circle.isVisible = false // 修改可见性

在这个例子中,Shape 协议通过属性要求统一了不同形状的接口,Circle 和 Rectangle 根据自身特点实现了 area 和 isVisible。

注意事项

  1. 实现必须匹配权限:如果协议要求 { get set },遵循者不能只提供 { get },否则会编译错误。
  2. 存储 vs 计算:协议不关心属性是存储属性还是计算属性,只要满足访问权限即可。
  3. 默认值不可用:协议中不能为属性指定默认值,默认值只能在遵循者中实现。
  4. 类型推断:属性类型必须明确指定,不能依赖类型推断。

小结

属性要求是协议的核心功能之一,它通过定义只读或可读写的属性,为遵循者提供了数据访问的规范。无论是简单的存储属性还是复杂的计算属性,Swift 的灵活性让属性要求的实现方式多种多样。在下一节,我们将探讨协议中的方法要求,进一步扩展协议的功能性。


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