努力了解Swift 3使用Nonfailable Initialisers覆盖可用的初始化程序

时间:2016-03-17 06:42:11

标签: swift initialization override subclass superclass

我试图学习在swift中覆盖可用的初始化器的概念并遇到以下声明:

  

委派超类初始化程序的唯一方法是   force-unwrap可用的超类初始化器的结果。

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

1 个答案:

答案 0 :(得分:5)

我不得不承认,“覆盖一个可用的初始化者”一节非常令人困惑。

以下示例应阐明此方案:

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

class Base {
    let name: String

    init?(name: String) {
        guard !name.isEmpty else {
            return nil
        }
        self.name = name
    }
}

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

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

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

class Derived: Base {
    let age: Int

    init(name: String, age: Int) {
        self.age = age
        super.init(name: name) //<- error 
    }
}

编译器发出以下错误:

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

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

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

1。强制打开可用的初始化程序:

class Derived: Base {
    let age: Int

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

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

let derived = Derived(name: "", age: 12)

在尝试从基类初始化程序中解包可选项时会导致致命错误:

fatal error: unexpectedly found nil while unwrapping an Optional value

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?
    }
}

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