swift 构造器tips

写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 的一个视频,这显然取决于类继承的工作方式。举个例子,如果一个父类调用了一个子类复写的方法,父类实际上将会调用子类复写后的方法实现(因为已经被复写了嘛),如果我们没有完全初始化好我们子类的属性,并且复写方法依赖于他们,那我们就遇到麻烦了。
这些原则有一些细微差别。在第二条原则中,一个便利构造器必须调用另一个构造器,其实不必是指定构造器,随便一个构造器都可以。如果你需要,你可以声明几个便利构造器,然后相互调用,这种链式调用时没问题的。但最终还是要符合第三条原则就对了。

你可能感兴趣的:(swift 构造器tips)