类(class)
引用类型:将一个对象赋值给另一个对象时,系统不会对此对象进行拷贝,而会将指向这个对象的指针赋值给另一个对象,当修改其中一个对象的值时,另一个对象的值会随之改变。
结构体(struct)
值类型:将一个对象赋值给另一个对象时,会对此对象进行拷贝,复制出一份副本给另一个对象,在修改其中一个对象的值时,不影响另外一个对象。
不同点:
1.struct属于值类型,class属于引用类型
2.class允许被继承,struct不允许被继承
3.class中的每一个成员变量都需要设置初始值或者设置成可选值,需要手动实现构造函数(constructor)来给每个属性设置初始值,否则会被编译器会报错,而struct中的成员变量可以不设置初始值,编译器会自动生成构造函数(constructor)
struct StructTest {
var name: String?
var age: Int?
}
class ClassTest {
var name: String?
var age: Int?
/// 如果不手动实现构造函数,编译器会报错
init(name: String?, age: Int?) {
self.name = name
self.age = age
}
init(name: String?, age: Int?) {
self.name = name
self.age = age
}
}
let structTest = StructTest(name: "abc", age: 10)
let classTest = ClassTest(name: "xyz", age: 20)
print("\(String(describing: structTest))")
print("\(String(describing: classTest.name)), \(String(describing: classTest.age))")
4.class遵守了协议没有实现协议方法会报错,而struct遵守了协议没有实现协议方法不会报错
struct StructTest: Equatable {
/// 如果实现协议方法,编译器不会报错
// static func == (lhs: ClassTest, rhs: ClassTest) -> Bool {
// if lhs.name == rhs.name {
// return true
// } else {
// return false
// }
// }
var name: String?
var age: Int?
}
class ClassTest: Equatable {
/// 如果实现协议方法,编译器会报错
static func == (lhs: ClassTest, rhs: ClassTest) -> Bool {
if lhs.name == rhs.name {
return true
} else {
return false
}
}
var name: String?
var age: Int?
/// 如果不手动实现构造函数,编译器会报错
init(name: String?, age: Int?) {
self.name = name
self.age = age
}
}
let structTest = StructTest(name: "abc", age: 10)
let classTest = ClassTest(name: "xyz", age: 20)
print("\(String(describing: structTest))")
print("\(String(describing: classTest.name)), \(String(describing: classTest.age))")
let structTest1 = StructTest(name: "efg", age: 10)
let classTest1 = ClassTest(name: "xyz", age: 30)
print(structTest == structTest1)
print(classTest == classTest1)
// 打印:StructTest(name: Optional("abc"), age: Optional(10))
// Optional("xyz"), Optional(20)
// false
// true
5.NSUserdefaults: struct不能被序列化成NSData对象,无法解档
6.swift和Object-C混合开发时,Object-C无法调用swift的struct, 因为在Object-C调用swift代码,对象需要继承于NSObject
7.swift的class像Object-C类一样,可以使用kvc、kvo、runtime的相关方法,适用于runtime系统。而这些struct不具备
8.struct也不能遵守NSObjectProtocol协议
9.内存分配:struct分配在栈中,class分配在堆中
知识延伸:“堆”和“栈”的区别,为什么访问struct比class块?
“堆”和“栈”并不是数据结构上的Heap跟Stack,而是程序运行中的不同内存空间。栈是程序启动的时候,系统事先分配的,使用过程中,系统不干预;堆是用的时候才向系统申请的,用完了需要交还,这个申请和交还的过程开销相对就比较大了。
栈是编译时分配空间,而堆是动态分配(运行时分配空间),所以栈的速度快。
从两方面来考虑:
1.分配和释放:堆在分配和释放时都要调用函数(MALLOC,FREE),比如分配时会到堆空间去寻找足够大小的空间(因为多次分配释放后会造成空洞),这些都会花费一定的时间,而栈却不需要这些。
2.访问时间:访问堆的一个具体单元,需要两次访问内存,第一次得取得指针,第二次才是真正得数据,而栈只需访问一次。