Swift 初始化器之谜

Swift Initializer Mystery

几个代码块:

这个有效:

import Foundation

class Class1 {
    init(param1: String?) {
        print("hello")
    }

    convenience init() {
        self.init(param1: nil)
    }
}

class SubClass1: Class1 {

}

let obj = SubClass1()

在上面的代码中,指定的初始化程序被传递给了SubClass1,因为SubClass1 没有提供自己的指定初始化程序。此外,便利初始化器也被传递下来。因此,这有效。

import Foundation

class Class1 {
    init(param1: String?) {
        print("hello")
    }

    convenience init() {
        self.init(param1: nil)
    }
}

class SubClass1: Class1 {
    override init(param1: String?) {
        print("hello 2")
        super.init(param1: nil)
    }
}

let obj = SubClass1()

这也行得通,因为 SubClass1 现在已经提供了自己指定的初始化程序。

import Foundation

class Class1 {
    init(param1: String?) {
        print("hello")
    }

    init(param2: String?) {
        print("world")
    }

    convenience init() {
        self.init(param1: nil)
    }
}

class SubClass1: Class1 {
    override init(param1: String?) {
        print("hello 2")
        super.init(param1: nil)
    }
}

let obj = SubClass1()

最后一行给出 "error: missing argument for parameter 'param1' in call"。 在这里,SubClass1有一个指定的初始化器,父类的便利初始化器也调用了相同的初始化器,那么为什么会出错?

这个

import Foundation

class Class1 {
    init(param1: String?) {
        print("hello")
    }

    required init(param2: String?) {
        print("world")
    }

    convenience init() {
        self.init(param1: nil)
    }
}

class SubClass1: Class1 {
    override init(param1: String?) {
        print("hello 2")
        super.init(param1: nil)
    }

    required init(param2: String?) {
        print("world")
        super.init(param2: nil)
    }
}

let obj = SubClass1()

这有效:

import Foundation

class Class1 {
    init(param1: String?) {
        print("hello")
    }

    init(param2: String?) {
        print("world")
    }

    convenience init() {
        self.init(param1: nil)
    }
}

class SubClass1: Class1 {
    override init(param1: String?) {
        print("hello 2")
        super.init(param1: nil)
    }

    override init(param2: String?) {
        print("world")
        super.init(param2: nil)
    }
}

let obj = SubClass1()

为什么需要覆盖所有指定的初始化程序才能让一个方便的初始化程序工作,它只调用指定的初始化程序之一?

此行为在 swift guide 中有明确说明。

Assuming that you provide default values for any new properties you introduce in a subclass, the following two rules apply:

Rule 1 If your subclass doesn’t define any designated initializers, it automatically inherits all of its superclass designated initializers.

Rule 2 If your subclass provides an implementation of all of its superclass designated initializers—either by inheriting them as per rule 1, or by providing a custom implementation as part of its definition—then it automatically inherits all of the superclass convenience initializers.

所以基本上,您的子类必须 override/define 超类的所有指定初始化程序才能继承超类的便利初始化程序。