深入理解代替单纯记忆
-
Swift初始化时会想尽一切办法确保初始化的安全、完备
-
就两种初始化方法:
designated initializer
和convenience initializer
-
designated
方法是指当前类完成初始化最基础的方法,它能满足所有stored property的初始化赋值 -
初始化方法中必须保证所有
stored property
都被赋上初始值。当然,optional
的属性可以不用明显的写出,默认会赋值为nil -
Swift初始化方法,子类一般不会将父类的
designated initializer
方法继承下来。为的就是,一旦可以继承的话,那我们就可以用父类的方法初始化一个子类对象了,此时子类的对象的属性可能并不okclass Food { var name: String init(name: String) { self.name = name } } class Noodle: Food { let width: CGFloat init(width: CGFloat) { self.width = width super.init(name: "Noodle") } }
-
当然,上面所说是指一般情况,有些情况下子类还是会继承父类的
designated initializer
方法的- 就是子类没有自定义
designated initializer
时 - 如果子类有实现
designated initializer
,即使子类并没有增加stored property
的情况下,此时子类依然不会继承父类初始化方法。因为自定义initializer
初始化方法中除了为stored property
赋值,可能还有其他自定义操作,既然写了designated initializer
方法,就说明可能有自己的实现,此时再继承了父类的实现就触发4中的问题了
class Food { var name: String init(name: String) { self.name = name } convenience init() { self.init(name: "unknown") } } class Noodle: Food { } let var1 = Noodle() let var2 = Noodle(name: "noddle")
- 就是子类没有自定义
-
一个复杂点的例子
- Food是父类,RecipeIngredient是子类
- 子类自定义实现了一个
designated initializer
,又重写了一个父类的designated initializer
同时用作convenience initializer
- 该情况下,父类的
convenience init()
方法会自动继承到子类中,因为子类实现了所有的的父类的designated initializer
,所以父类的convenience initializer
自动继承下来仍然会保证初始化的完备性
-
接着上面的例子,再来一层
- ShoppingListItem作为更子的类,由于引入的
purchased
属性有默认值,所以会自动继承父类的各种初始化方法,因为继承下来不会影响初始化的完备性
- ShoppingListItem作为更子的类,由于引入的
简单总结
还是那句话,为了确保初始化的完备性,能继承下去的就继承,一旦发现有影响完备性的漏洞,就不允许继承
convenience initializer
只能访问本类的初始化方法为此目的designated initializer
只能执行父类的designated initializer
也是如此- 所有规则都是如此;不记规则,只看原则
疑问
- 一方面Swift的子类不能继承父类的初始化方法,另一方面,子类在重写父类的初始化方法时却仍要写上
override
,这点不是很理解- 如果不能继承父类初始化方法,那子类实现和父类一致的初始化方法时照理应该理解为定义了一个全新的初始化方法,而非真的重写了