解释Swift中struct和class的主要区别:
1、存储方式和内存管理:
-
Struct(值类型):
- 存储在栈内存中
- 赋值时会复制一份新的数据
- 数据传递时是值传递
- 不需要手动管理内存
-
Class(引用类型):
- 存储在堆内存中
- 赋值时传递引用
- 数据传递时是引用传递
- 需要ARC管理内存
2、继承特性:
-
Struct:
- 不支持继承
- 可以遵循多个协议
- 更适合用于描述简单的数据类型
-
Class:
- 支持单继承
- 可以遵循多个协议
- 更适合用于描述复杂的对象关系
3、初始化方式:
-
Struct:
- 自动获得成员初始化器
- 不需要显式写init方法
- 所有属性必须有初始值
-
Class:
- 需要手动实现初始化方法
- 必须显式写init方法
- 可以使用convenience初始化器
4、可变性:
-
Struct:
- 需要使用mutating关键字修饰修改自身属性的方法
- 常量(let)声明后,所有属性都不可修改
-
Class:
- 不需要特殊关键字就可以修改属性
- 常量(let)声明后,仍可修改属性(引用不可变)
5、性能特点:
-
Struct:
- 内存分配在栈上,性能较好
- 适合小型、简单的数据结构
- 线程安全(值类型天然线程安全)
-
Class:
- 内存分配在堆上,性能相对较差
- 适合大型、复杂的数据结构
- 需要考虑线程安全问题
6、使用建议:
-
使用Struct的场景:
- 简单的数据类型(如Point、Size等)
- 需要值语义的场景
- 不需要继承的场景
- 需要线程安全的场景
-
使用Class的场景:
- 需要继承的场景
- 需要引用语义的场景
- 需要deinit析构函数的场景
- 需要共享数据的场景
7、案例
// Struct示例
struct Point {
var x: Int
var y: Int
mutating func moveBy(x: Int, y: Int) {
self.x += x
self.y += y
}
}
// Class示例
class Person {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
func birthday() {
age += 1
}
}
8、使用场景对比
// Struct的值类型特性
var point1 = Point(x: 1, y: 1)
var point2 = point1
point2.moveBy(x: 1, y: 1)
print(point1.x) // 输出1,point1不受影响
// Class的引用类型特性
let person1 = Person(name: "张三", age: 20)
let person2 = person1
person2.age = 21
print(person1.age) // 输出21,person1也被修改