为什么基类中的第二个初始化程序会中断编译?

时间:2019-05-16 18:25:35

标签: swift

给出基类,派生类和带有便捷初始化程序的扩展,如果将第二个初始化程序添加到基类中,则编译器将引发错误,如以下sscce

#!/usr/bin/env swift 
class A {
    required init(a : Int){}
    init(b: Int){} // when removing this initializer everything works fine
}

class B: A {
    required init(a : Int){ super.init(a: a) }
}

extension A {
    convenience init(c : Int) { self.init(a: c) }
}

let b: B = B(c: 1)

在基类中有两个初始化器时,会引发以下错误:

... error: incorrect argument label in call (have 'c:', expected 'a:')
let b: B = B(c: 1)
            ^~
             a

除了在这种情况下不是很有帮助的错误消息之外,我不确定这是预期的行为还是迅速的错误。

快速版本信息:

Apple Swift version 5.0.1 (swiftlang-1001.0.82.4 clang-1001.0.46.5)
Target: x86_64-apple-darwin18.5.0

1 个答案:

答案 0 :(得分:1)

来自Automatic Initializer Inheritance

  

假设为子类中引入的任何新属性提供默认值,则以下两个规则适用:

     

规则1
  如果您的子类没有定义任何指定的初始值设定项,它将自动继承其所有超类指定的初始值设定项。

     

规则2
  如果您的子类提供了其所有超类指定初始化器的实现(通过按照规则1继承它们,或通过提供自定义实现作为其定义的一部分),那么它将自动继承所有超类便利性初始化器。

init(b:)中没有class A的情况下,class B自动从扩展名继承init(c:),一切正常。

但是,当您将init(b:)添加到class A时,class B不再遵循这两个规则,因此class B不再自动从扩展名继承init(c:) 。由于class B现在只有一个init(a:)初始化程序,而没有其他初始化程序,因此会导致错误。

您可以通过覆盖init(b:)中的class B来解决问题。设置好之后,class B再次自动从扩展名中获取init(c:)