所以我有一个带有指定初始值设定项的类,它为每个存储的属性获取值。 我所有存储的属性也都有一个默认值,所以我假设这个类得到一个默认的init。
在我指定的init中,我调用super.init()
问题是,如果我在init的末尾调用它,它会将所有属性加载到默认值,但是如果我在开始时调用它,它就像我期望的那样工作。
这本书说:
安全检查1指定的初始化程序必须确保所有的 其类引入的属性在委托之前初始化 一个超类初始化器。
如上所述,只考虑对象的内存 一旦所有存储属性的初始状态为,就初始化 众所周知。为了满足这条规则,指定 初始化程序必须确保初始化所有自己的属性 在把它放到链子之前。
所以我不确定事情是否已经改变或我做错了什么?
代码:
class ORQuizViewController: UIViewController {
let imageView: UIImageView = UIImageView(image: nil)
let questionLabel: UILabel = UILabel()
let choicesArray: [BlackWhiteButton] = [BlackWhiteButton]()
let correctAnswer: Int = -1
init(image: UIImage!, question: String, choices: [String], answerIndex: Int) {
super.init()
imageView = UIImageView(image:image)
questionLabel = UILabel()
questionLabel.text = question
var tempChoices = [BlackWhiteButton]()
for choice in choices {
var choiceLabel = BlackWhiteButton()
choiceLabel.setTitle(choice, forState: .Normal)
tempChoices.append(choiceLabel)
}
choicesArray = tempChoices
correctAnswer = answerIndex
}
答案 0 :(得分:1)
正如您所观察到的那样,正确的解决方案是在分配最终值之前调用super.init
。正如您所说,安全检查1要求在委派之前初始化子类引入的所有属性 - 这由默认分配处理。
在初始化过程的第1阶段应用安全检查1。
然后发生初始化过程的第2阶段 -
第2阶段
从链条顶部向下工作,每个指定 链中的初始化程序可以选择自定义实例 进一步。初始化程序现在可以访问self并可以修改它 属性,调用其实例方法等。最后,任何 链中的便利初始化器可以选择自定义 实例并与自我合作。
因此,您需要在第2阶段分配最终值。
文档有点不清楚,但似乎你应该继续使用Objective C中调用超类init的典型约定。
答案 1 :(得分:-4)
我认为这是目标C,我不熟悉那种语言,但是一般来说,面向对象编程语言的操作,构造函数/初始化器必须从最小派生类调用到最派生类,以及相反顺序的析构函数。
可以这样想,如果基类是蛋糕,并且你的派生类增加了结冰,你就不能在蛋糕构建之前就把结冰放到位。
至于书中声明的含义,在调用初始化时,如果虚函数已经指向你的派生类'功能,那么你的类必须在你有机会调用虚函数之前进行初始化。
在C ++和C#中,语言分配对象,初始化最少派生的组件,将虚函数指向第一个派生类,然后构造它,依此类推。类不会调用超类初始化器。
我知道我没有回答你的问题,但也许这会帮助你弄清楚答案。首先调用super.init(),如果你打算调用super.init(),似乎是正确的行动方案。
也许这就是答案:如果虚函数确实指向你必须的覆盖,但你必须调用super.init(),那么你需要在调用虚函数时初始化你的数据成员,调用super.init()初始化内部类,然后继续初始化过程。这听起来对我来说非常不安全,但我认为没有别的办法可以解决。