为什么调用super.init()调用我的默认init()

时间:2014-09-14 03:00:53

标签: ios ios7 swift

所以我有一个带有指定初始值设定项的类,它为每个存储的属性获取值。 我所有存储的属性也都有一个默认值,所以我假设这个类得到一个默认的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
}

2 个答案:

答案 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()初始化内部类,然后继续初始化过程。这听起来对我来说非常不安全,但我认为没有别的办法可以解决。