我有以下代码:
class Parent {
var foo: Int
init(someNum: Int) {
self.foo = someNum
}
}
class Child: Parent {
}
var parent = Parent(someNum: 999)
println(parent.foo) // prints "999"
var child = Child(someNum: 3872)
println(child.foo) // prints "3872"
在Apple的2014 WWDC“Intermediate Swift”视频中,他说初始化程序默认不会继承,除非它的存储属性有默认值。但是,子类foo
中的Child
没有默认值,但它明确地继承了init(someNum:)
方法。我是否理解错误的解释或是否有其他事情发生?
答案 0 :(得分:11)
来自Apple文档:
默认情况下,子类不会继承其超类初始值设定项。 但是,如果超类初始值设定项会自动继承 满足某些条件。在实践中,这意味着你没有 需要在许多常见场景中编写初始化程序覆盖,并且可以 只要有最小的努力,就可以继承你的超类初始化器 这样做是安全的。
假设您为任何新属性提供默认值 在子类中引入,适用以下两个规则:
规则1 如果您的子类未定义任何指定的初始值设定项,则为 自动继承其所有超类指定的初始化器。
规则2 如果您的子类提供了所有子类的实现 超类指定初始化程序 - 通过按照继承它们 规则1,或通过提供自定义实现作为其一部分 定义 - 然后它自动继承所有的超类 便利初始化者。
即使您的子类增加了更多便利,这些规则也适用 初始化。
在您的情况下,您未在Child
中提供任何指定的初始值设定项。因此,唯一一个指定的初始值设定项已从Parent
继承。
如果您将Child
课程修改为:
class Child : Parent {
var age : Int
init (age : Int) {
self.age = age
super.init(foo: 10)
}
}
您将看到无法通过调用其超类初始值设定项来创建Child
类。
Read more.
修改强>
上述规则适用于更加不同的情况。也许文档对你来说有点混乱,但让我们停下来想一会儿。你有一个继承自超类的子类,它有一个属性foo
。现在,如果您的子类没有添加任何属性,或者添加了带有默认值的属性,则不需要与超类中的初始化程序不同的初始化程序,因此您可以安全地使用它。另一方面,如果添加没有默认值的属性,则无法使用超类中的初始化程序,因为添加的属性需要以某种方式初始化。编译器会抱怨,你必须做以下两件事之一: