文章目录

Swift 结构体:struct 与类的区别

发布于 2026-04-02 23:45:21 · 浏览 12 次 · 评论 0 条

Swift 结构体:struct 与类的区别

在 Swift 中,struct(结构体)和 class(类)都能用来定义自定义数据类型,但它们在内存管理、行为特性上存在根本差异。选择 struct 还是 class,直接影响程序的性能、安全性和可维护性。本文通过具体场景和代码对比,帮你快速掌握两者的核心区别。


1. 值类型 vs 引用类型

理解值类型和引用类型是区分 struct 和 class 的关键

  • struct 是值类型:当你把一个 struct 赋值给新变量,或作为参数传递时,Swift 会复制整个数据
  • class 是引用类型:赋值或传参时,Swift 只复制指向对象的引用(即“指针”),多个变量共享同一个实例。

验证值类型行为

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

var a = Point(x: 1, y: 2)
var b = a          // 复制 a 的值
b.x = 10           // 修改 b 不影响 a

print(a.x) // 输出 1
print(b.x) // 输出 10

验证引用类型行为

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

let p1 = Person(name: "Alice")
let p2 = p1        // p2 和 p1 指向同一个对象
p2.name = "Bob"

print(p1.name) // 输出 Bob(因为 p1 和 p2 共享同一实例)
print(p2.name) // 输出 Bob

2. 初始化与构造器

struct 自动获得成员逐一构造器,class 则没有

当你定义一个 struct 时,Swift 会自动为你生成一个初始化方法,参数顺序与属性声明一致:

struct Rectangle {
    var width: Double
    var height: Double
}

// 自动获得 init(width:height:)
let rect = Rectangle(width: 5.0, height: 3.0)

而 class 不会自动生成这种构造器,你必须手动实现:

class Circle {
    var radius: Double

    // 必须显式定义构造器
    init(radius: Double) {
        self.radius = radius
    }
}

let circle = Circle(radius: 4.0)

注意:如果 struct 的所有属性都有默认值,则可以不写任何构造器,直接使用 StructName() 初始化。


3. 继承能力

class 支持继承,struct 不支持

你可以让一个 class 继承另一个 class,获得其属性和方法,并可重写(override)行为:

class Vehicle {
    var speed: Double = 0.0
    func move() { print("Moving") }
}

class Car: Vehicle {
    override func move() {
        print("Car is moving at \(speed) km/h")
    }
}

而 struct 不能继承其他 struct 或 class。这是 struct 的硬性限制。


4. 可变性(Mutating)

在 struct 中修改自身属性需要标记为 mutating,class 则不需要

因为 struct 是值类型,默认情况下其方法不能修改自身的属性(保证不可变性)。若要修改,必须显式声明:

struct Counter {
    var count = 0

    mutating func increment() {
        count += 1  // 合法:因为方法是 mutating
    }
}

var c = Counter()
c.increment() // OK

而在 class 中,方法可以直接修改属性:

class CounterClass {
    var count = 0
    func increment() {
        count += 1  // 无需 mutating
    }
}

如果你尝试在非 mutating 方法中修改 struct 属性,编译器会报错。


5. 内存管理和性能

struct 存储在栈上(stack),class 实例存储在堆上(heap)

  • 栈内存分配快、释放快,适合小型、频繁创建销毁的数据(如坐标点、尺寸、颜色)。
  • 堆内存需要引用计数管理(ARC),有额外开销,适合大型、长期存在的对象(如用户、网络请求)。

因此,优先使用 struct 可提升性能并避免循环引用问题


何时使用 struct?何时使用 class?

下表总结了选择依据:

场景 推荐类型 理由
数据只是简单值(如 Point、Size、RGBColor) struct 值语义更安全,无共享副作用
需要继承或运行时多态 class struct 不支持继承
对象需要被多个地方共享并同步状态 class 引用语义天然支持共享
性能敏感的小型数据结构 struct 栈分配更快,无 ARC 开销
需要遵守 NSObject 或 Cocoa 框架协议 class 许多 UIKit/AppKit API 要求 class

通用原则除非你需要 class 的特性(如继承、引用语义),否则优先使用 struct。Apple 官方也建议:“Use structs for things that are values.”


验证你的选择是否合理

检查以下问题

  1. 这个类型是否代表一个“值”?(比如 (x: 10, y: 20) 就是一个位置值)
  2. 多个变量是否应该拥有独立副本?(修改一个不应影响另一个)
  3. 是否不需要继承?

如果三个问题答案都是“是”,就用 struct

反例:如果你发现 struct 中包含大量属性,且经常需要通过引用来共享状态,那它可能更适合改为 class。


// ✅ 合理使用 struct:表示几何矩形
struct Rect {
    var origin: Point
    var size: Size
}

// ❌ 不合理:试图用 struct 模拟 UI 控件(应使用 class)
struct Button {  // 错误:UI 控件需引用语义和继承
    var title: String
    var action: () -> Void
}

记住:struct 更适合“数据”,class 更适合“对象”。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文