类,结构体,枚举都可以定义初始化器
类有两种初始化器:指定初始化器和便利初始化器
//指定初始化器
init(parameters){
statements
}
//便利初始化器
convenience init(parameters){
statements
}
- 每个类至少有一个指定初始化器,指定初始化器是类的主要初始化器(如果自己不创建初始化器,那么类会默认创建一个指定初始化器,如果自己定义了指定初始化器,那么默认的初始化器就不存在了.但如果只是创建了便利初始化器,那么默认的指定初始化器还存在)
- 默认初始化器总是类的指定初始化器
- 类偏向于少量的指定初始化器,一个类通常只有一个指定的初始化器
初始化器的相互调用规则:
1.指定初始化器必须从它的直系父类调用指定的初始化器(有子类的时候)
2.便利初始化器必须从相同的类里调用另一个初始化器
3.便利初始化器最终必须调用一个同类的指定初始化器
- 当子类创建自己的指定初始化器时,先要把自己的存储属性初始化完成,然后再调用父类的指定初始化器(super.init(....) )
两段式初始化器:
第一阶段: 初始化所有存储属性
1.外层调用指定/便利初始化器(意思是比如开始创建实例对象的时候,会调用初始化器创建实例)
2.分配内存给实例,但未初始化(分配了内存空间,但数据还没写入,可以通过汇编查看)
3.指定初始化器确保当前类定义的存储属性都初始化
4.指定初始化器调用父类的指定初始化器,不断向上调用,形成初始化链
第二阶段:设置新的存储属性(已经初始化完了,可以设置新值)
1.从顶部初始化器往下,链中的没一个指定初始化器都有机会进一步定制实例
2.初始化器现在能够使用slef(访问,修改它的属性,调用它的实例方法等等)
3.最终,链中的任何便利初始化器都有机会定制实例以及使用self
- 安全检查:
- 指定初始化器必须在保证调用父类指定初始化器之前,其所在类定义的所有存储属性都要初始化完成
- 指定初始化器必须先调用父类的初始化器,然后才能为继承的属性设置新值(相当于前面中的第二阶段)
- 便利初始化器必须先调用同类中的其它初始化器,然后才能为任意属性设置新值(相当于前面中的第二阶段)
- 初始化器在第一阶段完成之前,不能调用任何势力方法,不能读取任何实例属性的值,也不能引用self
网友评论