结构体
在Swift标准库中,绝大多数的公开类型都是结构体,而枚举和类只占很小的一部分
比如:Bool、Int、Double、String、Array、Dictionary等常见类型都是结构体
struct Date {
var year: Int
var mouth: Int
var day: Int
}
var date = Date(year: 2019, mouth: 4, day: 2)
所有的结构体都有一个编译器自动生成的初始化器(initializer,初始化方法、构造器、构造方法) 上面最后一行调用的 可以传入所有成员值,用以初始化所有成员(存储属性,stored property)
结构体的初始化器
编译器会根据情况,可能会为结构体生成多个初始化器,宗旨是:保证所有成员都有初始值
思考:下面的代码能通过编译么?
struct Point {
var x: Int?
var y: Int?
}
var p1 = Point(x: 10, y: 10)
var p2 = Point(y: 10)
var p3 = Point(x: 10)
var p4 = Point()
可选项都有一个默认值nil,所以上面代码都可以编译通
自定义初始化器
一旦在定义结构体时自定义了初始化器,编译器就不会再帮他自动生成其他初始化器 所以如果你调用的话只有自己写的那个初始化器可以调用,其他原来系统帮你创建的现在都不会帮你创建了。
struct Point {
var x: Int?
var y: Int?
init(x: Int?, y: Int?) {
self.x = x
self.y = y
}
}
窥探初始化器的本质
以下2段代码完全等效
结构体内存结构
类
类的定义和结构体类似,但编译器并没有为类自动生成可以传入成员值的初始化器
类的初始化器
如果类的所有成员都在定义的时候指定了初始值,编译器会为类生成无参的初始化器,成员初始化是在这个初始化器中完成的
这两端代码完全相等
结构体和类的本质区别
结构体是值类型(枚举也是值类型),类是引用类型(指针类型)
对象的堆空间申请过程
在Swift中,创建类的实例对象,要向堆空间申请内存,大致流程如左图
值类型
值类型赋值给var、let或者给函数传参,是直接将所有内容拷贝一份,类似于对文件进行copy、paste操作,产生了全新的文件副本。属于深拷贝(deep copy)
值类型的赋值操作
你自定定义的结构体是没有提升性能的,只会深拷贝
在Swift标准库中,为了提升性能,String、Array、Dictionary、Set采取了Copy On Write。比如仅当有“写”操作时。才会真正执行拷贝操作,对于标准库类型的赋值操作,Swift能保证最佳性能,所以没有必要为了保证最佳性能来避免赋值,建议:不需要修改的,尽量定义成let。
struct Point {
var x: Int
var y: Int
}
var p1 = Point(x: 10, y: 10)
p1 = Point(x: 12, y: 13)
引用类型
引用类型赋值给var、let或者给函数传参,是讲内存地址拷贝一份。类似于只做一个文件的替身(快捷方式、链接)。指向的是同一个文件,属于浅拷贝(shallow copy)
值类型和引用类型的let
struct内容不可改,在栈区,class指向的var的可改,let的不可改,在堆区。
枚举、结构体、类都可以定义方法
一般吧定义在枚举、结构体、类内部的 函数,叫做方法
类和结构体的区别和联系:这是总结,以后可能会有相同的都是细节
区别1:
在 ** swift ** 中,包含三种类型(type): ** structure ** , ** enumeration ** , ** class **
其中structure和enumeration是值类型( ** value type ** ),class是引用类型( ** reference type ** )
区别2:
初始化:(没有自建的初始化器时)所有的结构体都有一个编译器自动生成的初始化器(initializer,初始化方法、构造器、构造方法) 可以传入所有成员值,用以初始化所有成员
类:编译器并没有为类自动生成可以传入成员值的初始化器
区别3:
值类型,存放在栈区(stack)struct内容不可改;引用类型,存放在堆区(heap)class指向的var的可改,let的不可改。
区别4:
值类型,即每个实例保持一份数据拷贝。值类型的赋值为深拷贝(Deep Copy)
引用类型,即所有实例共享一份数据拷贝,class 和闭包是引用类型。引用类型的赋值是浅拷贝(Shallow Copy)
区别5:
类调用的方法和属性在修饰上,struct只能用static,而class可以用static,也可以用class。(static修饰的类方法不能继承,class修饰的类方法可以继承)