写swift一时爽,一直写一直爽~~~
构造器的原则
- 一个指定构造器必须调用它直系父类的一个指定构造器。
- 一个便利构造器必须调用这个类自身的另一个构造器。
- 一个便利构造器最终一定会调用一个指定构造器。
指定构造器
init(sender: String, recipient: String) {
self.sender = sender
self.recipient = recipient
}
遍历构造器
convenience init(sender: String) {
self.init(sender: sender, recipient: sender)
}
父类与子类构造器的调用
- 上个错误的tips
class NoteMessage: Message {
let content: String
init(content: String, theUser: String) {
self.content = content
super.init(sender: theUser) // FIXME:这里调用父类的遍历构造器,会报错
}
第一条原则,一个指定构造器必须直接调用其直系父类的指定构造器。但我们尝试去调用它的一个便利构造器, 便会报错。
Why? Swift 设计成这样? 毕竟一个便利构造器最终都会调用一个指定构造器。也许这迫使我们去思考最合适的默认属性值,而不是只顾便利。
- 链式调用的Tips
// 链式调用构造器
convenience init() {
self.init(content: "")
}
convenience init(content: String) {
self.init(content: content, sender: "Myself")
}
convenience init(content: String, sender: String) {
// 最终在此处调用了指定构造器
self.init(content: content, sender: sender, recipient: sender)
}
- 子类初始化tips
init(content: String, sender: String, recipient: String) {
self.content = content // 首先初始化自己独有的属性
super.init(sender: sender, recipient: recipient) // 然后调用父类的指定构造器
// TODO: - 初始化继承自父类的属性
}
补充:
它满足了第一条原则了。我们首先设置了这个类自身的 content 属性,然后调用了父类的指定构造器,这就完成这个类的初始化了。这也是和 Objective-C 的差异,我们在 Objective-C 中是先初始化父类,再设置自己的属性。当然,回到 Swift 中,如果需要你也可在调用完其父类后再设置继承来的属性。
根据 WWDC 的一个视频,这显然取决于类继承的工作方式。举个例子,如果一个父类调用了一个子类复写的方法,父类实际上将会调用子类复写后的方法实现(因为已经被复写了嘛),如果我们没有完全初始化好我们子类的属性,并且复写方法依赖于他们,那我们就遇到麻烦了。
这些原则有一些细微差别。在第二条原则中,一个便利构造器必须调用另一个构造器,其实不必是指定构造器,随便一个构造器都可以。如果你需要,你可以声明几个便利构造器,然后相互调用,这种链式调用时没问题的。但最终还是要符合第三条原则就对了。
网友评论