Swift
中struct
和class
有什么不一样的地方?首先要先和大家提到一个观念,值类型ValueType
和引用类型ReferenceType
。其中 struct
是ValueType
而class
是ReferenceType
。
值类型的变量直接包含他们的数据,而引用类型的变量存储对他们的数据引用,因此后者称为对象,因此对一个变量操作可能影响另一个变量所引用的对象。对于值类型都有他们自己的数据副本,因此对一个变量操作不可能影响另一个变量。
- 定义一个struct
struct SRectangle {
var width = 200
}
- 定义一个class
class CRectangle {
var width = 200
}
1. 成员变量
struct SRectangle {
var width = 200
var height: Int
}
class CRectangle {
var width = 200
var height: Int // 报错
}
解释:
struct
定义结构体类型时其成员可以没有初始值,如果使用这种格式定义一个类,编译器是会报错的,他会提醒你这个类没有被初始化。
2. 构造器
var sRect = SRectangle(width: 300)
sRect.width // 结果是300
var cRect = CRectangle()
// 不能直接用CRectangle(width: 300),需要构造方法
cRect.width // 结果是200
解释:
所有的struct
都有一个自动生成的成员构造器,而class
需要自己生成。
3. 指定给另一个变量的行为不同
var sRect2 = sRect
sRect2.width = 500
sRect.width // 结果是300
var cRect2 = cRect
cRect2.width = 500
cRect.width // 结果是500
解释:
ValueType
每一个实例都有一份属于自己的数据,在复制时修改一个实例的数据并不影响副本的数据。而ReferenceType
被复制的时候其实复制的是一份引用,两份引用指向同一个对象,所以在修改一个实例的数据时副本的数据也被修改了。
4. 不可变实例的不同
let sRect3 = SRectangle(width: 300);
sRect3.width = 500 // 报错
let cRect3 = CRectangle()
cRect3.width = 500
解释:
struct
对于let
声明的实例不能对变量进行赋值,class
预设值是可以赋值let
实例的。注意Swift
中常用的String
、Array
、 Dictionary
都是struct
。
方法
struct SRectangle {
var width = 200
mutating func changeWidth(width: Int) {
self.width = width
}
}
class CRectangle {
var width = 200
func changeWidth(width: Int) {
self.width = width
}
}
解释:
struct
的方法要去修改property
的值,要加上mutating
,class
则不需要。
继承
struct
不能继承,class
可以继承。