【问题标题】:Struggling to Understand Swift 3 Overriding of Failable Initialisers with Nonfailable Initialisers努力理解 Swift 3 用不可失败初始化器覆盖可失败初始化器
【发布时间】:2016-07-03 08:58:39
【问题描述】:

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

委托给超类初始化器的唯一方法是 强制解包失败的超类初始化器的结果。

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

【问题讨论】:

  • 你最好使用标题“Overriding a Failable Initialiser”

标签: swift initialization overriding subclass superclass


【解决方案1】:

我不得不承认,“重写可失败的初始化程序”部分相当混乱。

以下示例应阐明这种情况:

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

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 结果从基类初始化程序传播到调用者 - 这使得调用者负责适当地处理可选选项。

【讨论】:

  • 非常详细的解释。比我所希望的要好。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-15
  • 1970-01-01
  • 1970-01-01
  • 2016-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多