1.初始化器在创建特定类型的实例时被调用
var focus = Fahrenheit()
struct Fahrenheit {
var temperature: Double
init() {
temperature = 32.0
}
}
2.默认的属性值
如上所述,你可以在初始化器里为存储属性设置初始值.另外,制定一个默认属性值作为属性声明的一部分.当属性被定义的时候你可以通过为这个属性分配一个初始值来指定默认的属性值.
let focus = Fahrenheit(temperature: 35)
print(focus)
struct Fahrenheit {
var temperature: Double = 32.0
}
Swift为所有没有提供初始化器的结构体或类提供了一个默认的初始化器来给所有的属性提供了默认值.这个默认的初始化器只是简单地创建了一个所有属性都有默认值的新实例.
let itemStruct = shoppingListItemStruct(name: "zhandan", quantity: 3, purchased: true)
let itemClass = shoppingListItemClass()
struct shoppingListItemStruct {
var name: String?
var quantity = 1
var purchased = false
}
class shoppingListItemClass {
var name: String?
var quantity = 1
var purchased = false
}
3.自定义初始化
可以提供初始化形式参数作为初始化器的一部分,来定义初始化过程中的类型和值得名称.初始化形式参数与函数和方法的形式参数具有相同的功能和语法.
let boilongPointOfWater = Celsius(fromTathhrenheit: 212.0)
let freezingPointOfWater = Celsius(fromkelvin: 273.15)
struct Celsius {
var temperatureInCelsius:Double
init(fromTathhrenheit fathrenheit:Double) {
temperatureInCelsius = (fathrenheit - 32.0)/1.8
}
init(fromkelvin kelvin:Double) {
temperatureInCelsius = kelvin - 273.15
}
}
4.在初始化中分配常量属性
在初始化的任意时刻 ,你都可以给常量属性赋值,只要他在初始化结束是设置了确定的值即可.一旦为常量属性被赋值,他就不能再被修改了.
let bett = SurveyQuestion(text: "How about beets?")
bett.ask()
bett.response = "I also like beet"
class SurveyQuestion {
let text: String
var response: String?
init(text:String) {
self.text = text
}
func ask() {
print(text)
}
}
5.结构体的成员初始化器
如果结构体类型中没有定义任何自定义初始化器,它会自动获得一个成员初始化器,不同于默认初始化器,结构体接受成员初始化器即使它的存储属性没有默认值.
let twoByTwo = Size(width: 2.0, height: 2.0)
struct Size {
var width = 0.0, height = 0.0
}
6.类的继承和初始化
1.所有类的存储属性(包括从它的父类继承的所有属性)都必须在初始化期间分配初始值;
2.Swift为类类型定义了两种初始化器以确保所有的存储属性接收一个初始值,这些就是所谓的指定初始化器和便捷初始化器.
3.指定初始化器是类的主要初始化器.指定初始化器可以初始化所有那个类引用的属性并且调用适合的父类初始化器来继续这个初始化过程给父类链.
4.类偏向于少量指定初始化器,并且一个类通常只有一个指定初始化器.指定初始化器是初始化开始并持续初始化过程到父类链的"传送"点.
5.每个类至少得有一个指定初始化器.如同在初始化器的自动继承里描述的那样,在某些情况下,这些需求通过从父类继承一个或多个指定初始化器来满足.
6.便捷初始化器是次要的,你可以在相同的类里面定义一个便捷初始化器来调用一个指定初始化器作为便捷初始化器来给指定初始化器设置默认形式参数.你可以可以为具体的使用情况或输入的值类型定义一个便捷初始化器从而创建这个类的实例.
7.如果你的类不需要便捷初始化器你可以不提供它.在为通用的初始化模式创建快捷方式以节省时间或者类的初始化更加清晰明了的时候使用便捷初始化器.
指定初始化器和便捷初始化器
简单的初始化器就是 init()
用convenience修饰符放到init关键字前定义便捷初始化器
7.类的初始化委托
指定初始化器必须从它的直系父类调用 指定初始化器
便捷初始化器必须从相同的类里调用另一个初始化器
便捷初始化器最终必须要调用一个指定初始化器.
8.两段式初始化
Swift的的初始化是一个两段式过程.在第一阶段,每一个存储属性被引入类分配了一个初始化值.一旦每个存储属性的初始状态被确定,第二个阶段就开始了,每个类都有机会在新的实例准备使用之前来定制它的存储属性.
两段初始化过程的使用让初始化更加安全,同时在每个类的层级结构给与了完备的灵活性.两段式初始化过程可以防止属性值在初始化之前被访问,还可以防止属性被另一个初始化器意外地赋予不同的值.
安全检查
指定初始化器必须保证在向上委托给父类初始化器之前,其所在类引入的所有属性都要初始化完成.
指定初始化器必须先向上委托父类初始化器,然后才能为继承的属性设置新值.如果不这样做指定初始化器赋予的新值将被父类中的初始化器所覆盖.
便捷初始化器必须委托于同类中其它初始化器,然后再为任意属性赋新值(包括同类里定义的属性).如果没有这么做,便捷初始化器赋予的新值将被自己类中其它指定的初始化器所覆盖.
初始化器在第一阶段初始化完成之前,不能调用任何实例方法,不能读取任何实例属性的值,也不能引用self作为值.
9.初始化器的继承和重写
不像在OC中的子类,Swift中的子类不会默认继承父类的初始化器.Swift的这种机制防止父类的简单初始化器被一个更专用的子类继承并用来创建一个没有完全或错误初始化的新实例的情况发生.只有在特定情况下才会继承父类的初始化器.
如果你想自定义子类来实现一个或多个父类相同的初始化器,你可以在子类中为那些初始化器提供定制的实现.
当你写的子类初始化器匹配父类指定初始化器的时候,你实际上可以重写那个初始化器.因此,在子类初始化器定义之前你必须写override修饰符.如同默认初始化器所描述的那样,即使是自动提供的默认初始化器你也可以重写.
10.初始化器的自动继承
如果你的子类没有定义任何指定初始化器,它会自动继承父类所有的指定初始化器.
如果你的子类提供了所有父类指定初始化器的实现一一要么是通过规则1继承来的,要么通过在定义中提供自定义实现的一一那么它自动继承所有的父类便捷初始化器.
11.可失败初始化器
定义类,结构体或枚举初始化时可以失败在某些情况下会管大用.这个失败可能由以下几种方式触发,包括给初始化传入无效的形式参数值,或缺少某种外部所需的资源,又或是其他阻止初始化的情况.
为了妥善处理这种情况可能失败的情况,在类,结构体或枚举中定义一个或多个失败的初始化器.通过在init关键字后面添加问号(init?)来写.
12.必要初始化器
在类的初始化器前添加required修饰符来表明所有该类的子类都必须实现该初始化器.
13.反初始化器
在类实例被释放的时候,反初始化器就会被立即调用.你可以使用deinit关键字来写反初始化器,就如同写初始化器要用iniit关键字一样.反初始化器只在类类型中有效.
反初始化器会在实例被释放之前自动被调用,你不能自动调用反初始化器.父类的反初始化器可以被子类继承,并且子类的反初始化器实现结束之后父类的反初始化器会被调用.父类的反初始化器总会被调用,就算子类没有反初始化器.
每一个类当中只能有一个反初始化器.反初始化器不接收任何形式参数,并且不需要写圆括号.
deinit
{
}
|