Swift——类与结构体
一.结构体
在swift的标准库中,大部分的类型都是结构体,比如:Int,Double,String,Array,Dictionary等等,它们都是结构体。
结构体定义如下:
struct Person {
var name:String
var age:Int
}
1.结构体的初始化
所有结构体都有一个编译器自动生成的初始化器,这样保证了结构体成员都有初始值。
如图:
如果你自定义了一个初始化器,那么编译器就不会生成初始化器,初始化器定义方式如下:
我们在定义结构体初始化时,一定要保证所有的结构体成员都有初始化值,否则会报错。
二.类
类与结构体十分类似,它们的不同点如下:
- 类可以继承,结构体不可以继承
- 类的实例类型可以通过使用类型转换进行检查和解释
- 类有析构函数(deinit()),该函数可以用来释放其分配的资源
- 引用计数允许对一个类实例有多个引用
- 编译器不会为类自动提供成员初始化器
1.类的初始化
与结构体不同,编译器不会提供初始化器,所以,如果你的类里面的成员没有初始化值,那你需要为类提供一个指定的初始化器,,否则编译不通过。
初始化如图:
也可以创建便捷初始化器,但是使用便捷初始化器,必须先调用主初始化器,如图:
在swift中,指定初始化器和便捷初始化器有以下规则:
规则1:指定初始化器必须保证在向上委托给父类初始化器之前,其所在类引入的所有属性都要初始化完成。
规则2:指定初始化器必须先向上委托父类初始化器,然后才能为继承的属性设置新值。如果不这样做,指定初始化器赋予的新值将被父类中的初始化器所覆盖
规则3:便捷初始化器必须先委托同类中的其它初始化器,然后再为任意属性赋新值(包括同类里定义的属性)。如果没这么做,便捷构初始化器赋予的新值将被自己类中其它指定初始化器所覆盖。
规则4:初始化器在第一阶段初始化完成之前,不能调用任何实例方法、不能读取任何实例属性的值,也不能引用 self 作为值。
如图:
class Father {
var name:String
var age:Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
class Son:Father{
var height:Double
var weight:Double = 20
init(height: Double) {
print("\(self.weight)")
self.height = height
super.init(name: "2", age: 20)//规则1,调用父类初始化器前,自身类成员必须初始化
show() //规则4 所有属性初始化之后,才可以调用实例方法
print(self)
self.name = "222"//规则2,对继承的属性赋新值,必须先委托父类初始化器
}
func show(){
print("Son的show方法")
}
convenience init() {
self.init(height:110)
self.weight = 120//规则3
self.height = 170
}
}
可失败初始化器:这种初始化器是当初始化失败时,我们允许类返回nil用来表示类初始化失败,初始化失败的原因可能是外部参数输入不合法,或不满足可初始化的条件,其定义如下:
必要初始化器:在类初始化器前添加required关键字来表示该类的所有子类都必须实现该初始化器。如图:
三.值类型与引用类型
swift里面的类型分为两种:值类型和引用类型
- 值类型:每个实例都保留了一分独有的数据拷贝,一般以结构体(struct)、枚举(enum)或者 元组(tuple)的形式出现。
- 引用类型:每个实例共享同一份数据来源,一般以类(class)的形式出现。
1.值类型与引用类型的区别:
值类型的变量在赋值的时候是深拷贝,当一个变量的属性值被修改,另一个变量的值不会变。
引用类型的变量不会直接存储具体的实例对象。
这里可以看见,p1和p2对应的地址是相同的,当修改一个实例对象的属性值,另一个也会被修改。
四.类和结构体的存储位置
引用类型和值类型还有一点不同就是存储位置不同,值类型存储在栈(stack)上,而引用类型存储在堆(heap)上。
五.如何使用结构体和类
因为结构体存储在栈上,而类存储在堆上,因此在创建和销毁上,类消耗的时间和内存会比较多,同时,类是引用类型,在赋值时会有引用计数,这里也会造成成本,因此,创建结构体会比创建类所消耗的时间和内存更少。
使用值类型的时机:
- 用==运算符比较实例数据时
- 希望实例被拷贝后仍保持独立状态时
- 数据会被多个线程使用时
使用引用类型的时机:
- 用==运算符比较实例身份时
- 希望创建一个可以共享,可变对象时
五.类的生命周期
1.Swift的编译过程
iOS开发的语言都是通过LLVM进行编译,如图:
- OC通过clang编译器,编译成IR文件,然后再生成可执行文件.o(这里也就是我们的机器码)
- Swift则是通过Swift编译器编译成IR文件,然后在生成可执行文件.o。
Swift编译相关命令:
//分析输出AST
swiftc main.swift -dump-parse
//分析并检查类型输出AST
swiftc main.swift -dump-ast
//生成中间体语言(SIL),未优化
swiftc main.swift -emit-silgen
//生成SIL,优化后
swiftc main.swift -emit-sil
//生成LLVM中间体语言(.ll文件)
swiftc main.swift -emit-ir
//生成LLVM中间体语言(.bc文件)
swiftc main.swift -emit-bc
//生成汇编
swiftc main.swift -emit-assembly
//编译生成可执行.out文件
swiftc -o main.o main.swift