如果我有一个swift子类:
self
self
上的任何属性
我还需要在子类的init()
方法中调用super.init()
吗?
*注意:由于上面1和2中列出的细节,这是一个与here on SO问答不同的问题。
发布于 2014-08-12 14:08:46
不,你没必要这么做。
假设您有以下类。
class a {
let name: String
init() {
name = "james"
}
}
class b: a {
let title: String
override init() {
title = "supervisor"
}
}
如果使用实例化变量
let myVar = b()
然后,
b
中的
override init()
将称为a
中的init()
将称为即使您没有显式调用super.init()
。
Chris Laettner在快速用户的电子邮件列表中证实了这一点。当你的超类只有一个带有零参数初始化的指定初始化器时,它就开始起作用了。这就是为什么从NSObject派生时不必调用super.init()的原因。
*感谢Wingzero在下面的评论
发布于 2014-08-12 16:57:21
从文档中:
指定的初始值设定项必须从其直接超类调用指定的初始值设定项。
另外,关于自动初始化器继承:
假设您为在子类中引入的任何新属性提供默认值,则适用以下两个规则:
规则1如果你的子类没有定义任何指定的初始值设定项,它会自动继承所有超类指定的初始值设定项。
规则2如果您的子类提供其所有超类指定的初始化器的实现-通过按照规则1继承它们,或者通过提供自定义实现作为其定义的一部分-那么它将自动继承所有超类便利初始化器。
即使您的子类添加了更方便的初始值设定项,这些规则也适用。
因此,你的问题的答案如下:
您的子类将始终调用您的父类的指定初始值设定项。如果您没有编写初始化器,并且编译器没有错误,那么它使用了自动初始化器继承。如果你写了一个初始化器,但它没有显式地调用相关的上游(或侧流)初始化器,那么它将在你的初始化器结束时自动为你完成。
此外,链式初始化器的工作方式是一个两阶段的过程。在第一阶段,它从子类开始到超类,为任何参数分配默认值。在第二阶段,该过程向后运行,从超类开始,以子类结束,在子类中完成参数的自定义并被覆盖。
这意味着您必须首先在每个init()
中设置变量,然后可以自由调用(或不调用) super.init()
并运行自定义代码。因此,正如你上面所问的,如果你想让超级程序的初始化在开始时运行,那么“开始”就在你创建变量之后:
class a {
var name: String
init() {
name = "james"
println("a")
}
}
class b: a {
let title: String
override init() {
title = "supervisor"
super.init()
self.name = "john"
println("b")
}
}
let x = b()
这将打印a,然后打印b。
发布于 2014-08-12 17:52:14
是的,指定的初始化器需要向上委托,所以它必须调用super.init()。如果您不编写这行代码,编译器将为您编写代码。
因此,您不必显式编写super.init(...)
,但子类必须显式编写,即使只是在幕后。
但请记住,在第一阶段中,您需要设置子类中的属性,然后必须调用super.init()。在第二阶段,您可以更改所有继承的属性。我认为super.init()
是第一阶段和第二阶段之间的完美分隔符。
从文档中:
安全检查2
在为继承的属性赋值之前,指定的初始值设定项必须将委托给超类初始值设定项。如果不为,则指定的初始化器分配的新值将被超类覆盖为,作为其自身初始化的一部分。
https://stackoverflow.com/questions/25257224
复制相似问题