前言
存储属性的初始赋值
类
的 存储属性需要有默认值
,而 结构体、枚举不需要
类设置默认值方式也有两种:一种是 定义存储属性时设置默认值(Optional)
,另一种是通过 初始化器为存储属性设置默认值
类的初始化器有两种,一种 指定初始化器
,另一种 便捷初始化器
指定初始化器又分为两种:一种 初始化器
不带参数,另一种 自定义初始化器
带参数
默认值
可选类型
的存储属性,不需要设置默认值,因为它本身 可能有值
或 可能没有值
,编译器会自动设置默认的初始化器
1 2 3 4 5 6 class Person { // 1、声明一个 Optional 默认值 var name: String? // 2、直接设置默认值 var name: String = "" }
1 2 3 4 5 6 class Person { var name: String { // 在这个闭包中给 name 创建一个默认值 return "ZJ" } }
指定初始化器为存储属性设置默认值
初始化器创建实例时被调用,最简答的形式是不带任何参数的实例方法,已关键字 init
命名,即 指定初始化器
1 2 3 clas Person { var name: String? }
可以通过 输入参数
来自定义初始化器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Person { var name: String // 0.不带参数 init() { self.name = "ZJ" } // 1.实际参数和形式参数相同 init(name: String) { self.name = name } // 2.实际参数 和 形式参数 不同 init(to name: String) { self.name = name } // 3.通配符实际参数 init(_ name: String) { self.name = name; } } let p = Person(name: "ZJ") let p1 = Person(to: "ZJ") let p2 = Person("ZJ")
注:指定初始化器分为两种:一种是不带参数,一种是带参数 初始化器可以有任意数量
类的继承和构造 类中的所有存储属性->包括继承父类的所有存储属性:都必须在构造过程中 设置默认值
1、swift
中为类提供了两种初始化器:指定初始化器
和 便捷初始化器
类中 主要的初始化器
,设置类中所有属性默认值,并往上调用父类的初始化器设置所有属性的默认值
类中 次要的、辅助型的初始化器
,可以调用类中的指定初始化器,并提供默认值
2、指定初始化器和便捷初始化器语法
1 2 3 init(parameters) { statements }
便捷初始化器,需要在 init
前放置 convenience
关键字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Person { // 未设置默认值的存储属性 var name: String // 指定初始化器 用来给存储属性设置默认值 init(name: String) { self.name = name } // 便捷初始化器 convenience init() { // 横向代理:必须调用一个指定的初始化器 self.init(name: "ZJ") } } let p = Person() print(p.name)
类的初始化器代理规则 1、指定初始化器必须调用其直接父类的指定初始化器 2、便捷初始化器必须调从同类调用一个指定初始化器 3、便捷初始化器最终必须调用一个指定初始化器
更方便的记忆方法 1、指定初始化器必须总是向上代理 2、便捷初始化器必须是横向代理
3、初始化器继承和重写
子类默认是 不继承
父类的初始化器,实际上是通过 重写
父类的初始化器,切需要带上 override
关键字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 // 继承和重写 class Person { var name: String init(name:String) { self.name = name } } class Student: Person { // 重写父类的初始化器 override init(name: String) { var newName = "my name is \(name)" super .init(name: newName) } } let s = Student(name: "ZJ") print(s.name) ======= my name is ZJ
1、如果子类没有定义任何初始化器,它将自动继承父类的所有指定初始化器 2、如果子类实现了继承自父类的指定初始化器,那么它将自动继承父类的便捷初始化器
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class Person { var name: String init(name:String) { self.name = name } convenience init() { self.init(name: "ZJ") } } let p = Person() print(p.name) // 打印结果 ZJ // 子类 class Student: Person { var age: Int // 本类的指定初始化器 init(name: String,age: Int) { self.age = age // 实现父类的指定初始化器 super.init(name: name) } convenience override init(name: String) { self.init(name: name, age: 32) } } let s = Student() let s1 = Student(name: "ZJ") let s2 = Student(name: "ZJ", age: 32) print(s.age) // 打印结果 32
安全检查
子类指定初始化器向上委托父类初始化器前,子类的所有属性都要完成初始化
之类指定初始化器必须先向上委托父类初始化器,才能修改父类的所有属性
便捷初始化器必须先委托同类初始化器,才能为任意属性赋值
方法的调用在所有指定初始化器之后。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 // 安全检查 class Person { var name: String var age: Int // 指定初始化器 init(name: String, age: Int) { self.name = name self.age = age } convenience init(){ self.init(name: "[Unnamed]", age: 0) } } class Teacher: Person { // 工资 var salary: Int // 自己的指定初始化器 init(name: String, age: Int, salary: Int) { // 1.先赋值自己的所有属性 self.salary = salary // 2.调用父类的指定初始化器 super.init(name: name, age: age) // 3.修改父类的所有属性 self.name = name + "老师" // 6.调用方法 test() } func test() { print("test") } convenience init(salary: Int) { // 4.必须调用本类的指定初始化器 self.init(name: "ZJ", age: 32, salary: salary) // 5.调用本类的指定初始化器后,才能赋值本类的所有属性 self.salary = self.salary + 1000 } }
失败初始化器 如果在构造过程有可能失败,则需要定义一个可失败的初始化器,在 init
关键字 后面
添加 ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Person { var age: Int init?(age: Int) { if age > 200 { return nil } age = age } } let p = Person(age: 300) print(p) ===== nil
反初始化器
1 2 3 deinit { // perform the deinitialization }
必要初始化器
在类的初始化器前加 required
修饰符表明所有该子类必须实现该初始化器
1 2 3 4 5 6 // 必要初始化器 class SomeClass { required init(){ // 初始化器的实现代码 } }
子类重写父类的必要初始化器时,子类的初始化器前也添加 required
关键字,表明可继承
1 2 3 4 5 6 7 // 必要初始化器 class SomeSubClass: SomeClass { required init(){ // 初始化器的实现代码 } }