使用 Swift 开发时,你总会遇到至少一次让自己停下来思考的时刻。
“这个该用 class 还是 struct?”
刚开始学习 Swift 时,我也只是凭感觉在两者之间做选择。直到遇到奇怪的 bug,才真正认真研究它们的区别。
先说结论。
如果没有特殊理由,优先选择结构体(struct)。
只有在确实需要“共享的一份状态”时,才使用类。
Apple 的官方指南也持相同观点。今天我们逐一说明原因。
核心总结(3 点)
先为忙碌的读者总结重点。
- 结构体是值类型。复制后会变成完全不同的值。
- 类是引用类型。即使复制,仍然指向同一个实例。
- 如果不确定,先用 struct,只有需要继承或共享状态时才用 class。
记住这三句话,就完成一半了。
值类型和引用类型有什么区别?
只听文字说明确实容易困惑。直接看代码最快。
先看结构体。复制的瞬间,两者就完全独立了。
struct Point { var x = 0 }
var a = Point()
var b = a // 值已复制
b.x = 10
print(a.x, b.x)
// 输出: 0 10
即使修改b,a也保持不变,因为它们各自拥有自己的值。
接下来是类。代码看起来相似,但结果不同。
class Box { var x = 0 }
let a = Box()
let b = a // 引用已复制(同一个对象)
b.x = 10
print(a.x, b.x)
// 输出: 10 10
明明只修改了b,a也变成了 10。
因为两者指向同一个实例。这个曾经困扰我的 bug,原因正是如此。
那么什么时候该用哪一个?(选择标准)
在实际开发中做判断时,我会在脑中回想这张表。
| 情况 | 判断 |
|---|---|
| 只用于存放数据的模型 | 结构体 |
| 希望复制后彼此独立 | 结构体 |
| 必须使用继承 | 类 |
| 在多个地方共享同一个实例 | 类 |
| 需要与 Objective-C 互操作 | 类 |
再展开一点,可以总结为下面这样。
- 如果要表示坐标、颜色、大小等值本身,使用结构体很自然。
- 如果多个地方需要共同查看同一份状态,例如屏幕控制器或网络管理器,就应该使用类。
- Apple 的 SwiftUI 也出于同样的原因将 View 定义为 struct:轻量且易于预测。
顺便一提,Swift 标准库中的Array、String和Dictionary全都是结构体。这说明值类型是多么基础。
为什么优先推荐结构体
值类型更容易预测。
不用担心传出的值在其他地方被悄悄修改。即使传给函数,原始值也很安全。
在多线程环境中也更安心。因为没有共享状态,数据竞争会减少。
相反,类虽然强大,却需要谨慎使用。如果同一个实例被多个地方持有,就很难追踪值在哪里发生了变化。
因此养成“默认使用 struct,需要时才用 class”的习惯,能大幅减少 bug。
什么时候使用,什么时候避免
最后,将判断标准简要总结如下。
- 使用结构体:以数据为中心的模型、需要独立副本,以及重视线程安全时
- 使用类:需要继承、必须共享一个实例,或标识(identity)具有意义时
- 避免:习惯性地为简单模型使用 class,或明明需要共享却强行用 struct 绕开
面试时可以这样回答
问:结构体和类最大的区别是什么?
结构体是值类型,类是引用类型。复制结构体会得到完全独立的值,而复制类仍然指向同一个实例。此外,只有类支持继承并可以定义 deinit。
问:Swift 为什么推荐使用结构体?
因为值类型没有共享状态,副作用更少,也更容易预测。原始值不会被意外修改,在多线程环境中也更安全,有助于减少 bug。
一开始我也以为这只是语法差异,但越深入研究,越发现这是设计问题。
熟悉今天的判断标准后,从下一个项目开始就不会那么犹豫了。先问自己:是值,还是共享?

