Swift中的Struct与Class:何时以及为何选择结构体

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Struct还是Class?Swift开发者的永恒问题



每个开始用Swift编程的人迟早都会遇到这个问题。乍一看,这两种结构都可以创建包含数据和方法的对象。但为什么在Stack Overflow上这个问题获得了数千次浏览,而经验丰富的开发者却越来越倾向于选择结构体呢?



答案很简单:因为在struct和class之间的选择直接影响您应用程序的性能、线程安全性和架构。在本文中,我们不仅会讨论理论,还会分析实际示例和场景,在这些场景中Struct明确优于Class。



如果您正在使用Swift,并且仍然“习惯性地”使用来自Objective-C的类——那么本文就是为您准备的。准备好重新思考您的方法吧。


主要区别:值类型 vs 引用类型



在深入细节之前,让我们回顾一下根本区别:



  • Struct 是 值类型。在赋值或传递给函数时,会创建数据的副本。
  • Class 是 引用类型。在赋值或传递给函数时,传递的是对内存中同一对象的引用。


看似小事。但正是这个“原子级”的区别衍生出了我们接下来要讨论的所有后果。



示例1:Class的意外行为



class PersonClass {    var name: String    init(name: String) {        self.name = name    }}

struct PersonStruct { var name: String}

// 测试类let person1 = PersonClass(name: "安娜")let person2 = person1person2.name = "玛丽亚"

print(person1.name) // 玛丽亚!person1也被改变了print(person2.name) // 玛丽亚


发现问题了吗?修改了person2的名字,却不经意间也修改了person1的名字。因为它们是内存中的同一个对象。在小例子中这并不严重,但在实际项目中,这种“副作用修改”可能导致难以追踪的bug。



// 测试结构体var person3 = PersonStruct(name: "安娜")var person4 = person3person4.name = "玛丽亚"

print(person3.name) // 安娜!一切正常print(person4.name) // 玛丽亚


结构体的行为是可预测的:每个变量拥有自己独立的数据副本。这既安全又透明。



何时Struct是显而易见的选择?



Apple在其文档中建议默认使用struct。让我们列举一下结构体毫无疑问胜出的具体场景。



1. 应该不可变的数据



如果您处理的是创建后不应更改的模型(例如,服务器请求的结果),那么使用具有常量属性的struct是理想选择。



struct UserProfile {    let id: Int    let name: String    let email: String}

// 创建后即可放心。数据受到保护,不会被意外修改。let profile = UserProfile(id: 1, name: "伊万", email: "ivan@example.com")


使用类时,如果属性声明为var,您仍然可能错误地修改name。而使用结构体,编译器会迫使您考虑不变性。



2. 小型、自包含的实体



如果您的模型描述的是简单的东西——坐标、尺寸、颜色、金额——请使用struct。这既合乎逻辑又高效。



struct Point {    var x: Double    var y: Double}

struct Money { var amount: Double var currency: String}

struct Rectangle { var origin: Point var size: Size}


这些类型不需要继承和引用管理。它们只是

博客

书籍推荐