给出基类,派生类和带有便捷初始化程序的扩展,如果将第二个初始化程序添加到基类中,则编译器将引发错误,如以下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
答案 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:)
。