努力理解Swift 3的失败初始化与非失败初始化的覆盖

3 overriding initialization subclass superclass swift

我正在尝试快速了解覆盖失败的初始化程序的概念,并且遇到了以下语句:

委派给超类初始值设定项的唯一方法是强制展开可失败的超类初始值设定项的结果。

教科书没有提供任何代码来真正解释其真正含义?有人可以向我解释一下吗?如果附带代码示例,那就更好了!

Cou*_*per 5

我必须承认,“覆盖失败的初始化程序”部分相当混乱。

下面的示例应阐明这种情况:

假设您有一个带有失败的初始化程序的基类:

class Base {
    let name: String

    init?(name: String) {
        guard !name.isEmpty else {
            return nil
        }
        self.name = name
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,失败的初始化程序将返回Optional。

在此,初始化程序要求您传递一个非空字符串,否则,初始化程序将“失败”-也就是说,它返回一个可选值,其值nil分别为.None

现在,让我们定义一个派生自的类Base。在第一个版本中,这将无法编译,很难!

class Derived: Base {
    let age: Int

    init(name: String, age: Int) {
        self.age = age
        super.init(name: name) //<- error 
    }
}
Run Code Online (Sandbox Code Playgroud)

编译器发出以下错误:

error: a non-failable initializer cannot chain to failable initializer 'init(name:)' written with 'init?'
        super.init(name: name)
              ^
Run Code Online (Sandbox Code Playgroud)

这里的问题是,子类的非失败初始化程序将失败的基类初始化程序委派给失败的基类初始化程序。

我们有两种方法可以解决此问题:

1.强制展开失败的初始化程序:

class Derived: Base {
    let age: Int

    init(name: String, age: Int) {
        self.age = age
        super.init(name: name)!   // <- force unwrap 
    }
}
Run Code Online (Sandbox Code Playgroud)

此解决方案的警告是,如果将空值传递name给子类初始化程序,例如

let derived = Derived(name: "", age: 12)
Run Code Online (Sandbox Code Playgroud)

尝试从基类初始化程序中取消可选内容时,它将导致致命错误:

fatal error: unexpectedly found nil while unwrapping an Optional value
Run Code Online (Sandbox Code Playgroud)

 2.使子类初始化程序也失败:

class Derived: Base {
    let age: Int

    init?(name: String, age: Int) {  // use failable initialiser
        self.age = age
        super.init(name: name)  // <- propagate the failure with init?
    }
}
Run Code Online (Sandbox Code Playgroud)

此解决方案只是将nil结果从基类初始化程序传播到调用方-这使调用方负责适当地处理可选内容。