@H_502_1@类继承方法重载
可使用 override 修饰
final 关键字
- 用final 防止重写,final关键字可以修饰类、属性、方法和下标。
- final 不可以修饰方法中的局部变量,也不能修饰全局变量。
- 在类中使用 static修饰类的方法、属性,表示不可被重写,相当于 class + final 的效果
构造器
类的两种构造器
init(形参){}
- 指定构造器定义: 一个或者多个初始化所有实例属性,可调用父类的构造器,然后初始化本类的存储属性
- 便利构造器定义: 次要的、辅助行的构造器,通过调用同一个类的其他构造器(可以是指定、也可是便利,但最原始的一定指定构造器)完成初始化, 用convenience 修饰。
构造器链
两段式构造
Swift类的构造要两个阶段完成
第一阶段: 为存储属性分配内容,使用本类构造器初始化由本类定义的存储属性
第二阶段: 从最顶层父类开始,沿着顶部构造器链往下,每个构造器都可再次修改存储属性。
这个流程解决的问题
Swift内部检查
- 指定构造器必须先初始化自己类的实例存储属性,才能向上调用父类构造器
- 指定构造器必须向上调用父类构造器,才能得到继承下来的属性,然后才能赋值。 顺序不对会导致刚赋值但是被构造器覆盖掉了。
- 便利构造器先调用同类的其他(指定)构造器,才能对属性赋值。 和2检查原因一样,担心赋值被覆盖
- 构造器在第一阶段完成前,不能调用实例方法,不能读取实例属性。 (实际上是对第二阶段的进一步解释)
我对构造器的理解:
1. 指定构造器:最原始可以完成初始化的方法
2. 便利构造器:在指定构造器基础上方便定制化的一些方法,最终还是依赖指定构造器。
这样可以方便理解构造器链。
构造阶段,基本原则
1. 准确性(赋值了就一定得到赋值的操作结果,无二义性)
2. 顺应类继承关系。
3. 如果一个对象没有初始化,对它属性操作就是非法的。
结合第一阶段和第二阶段构造,再参考内部检查就容易理解了
构造器的继承和重写
四种情况
子类指定 <- 父类指定 Y
子类指定 <- 父类便利 N 子类是不会调用父类的便利构造器的
子类便利 <- 父类指定 Y
子类便利 <- 父类便利 N 子类是不会调用父类便利构造器的
结论:
可能失败的构造器
可能失败的构造器的传播
普通构造器不能调用同一个类型的可能失败的构造器
子类必须包含的构造器
定义:申明所有子类必须包含该require构造器(指定和便利均可),表示为 require init() {}
析构器
deinit 方法,没有返回值,没有参数,所以不能重载 deinit { } swift 会自己调用父类的deinit方法