在swift中调用超级指定初始化程序之前初始化属性值的目的是什么?

时间:2015-12-16 08:33:40

标签: swift

这是我的代码:

class Base
{
    init(){
        print("Super!")
    }
}

class Test : Base
{
    internal var y:Int
    convenience init(_ a:Int)
    {
        self.init()
        print("\(a)")
    }
    override init()
    {
        super.init() //Error!!! Property 'self.y' not initialized at super.init call
        y = 123
    }
}

我认为应该编译:

y在课程' Base'中是不可见的,y和超级课程的初始化顺序是否真的没有物质

2 个答案:

答案 0 :(得分:5)

你的论点

  

我认为应该编译:

     

y在类' Base'中是不可见的,是否是初始化的顺序   我和超级课程并不重要。

不正确,是安全的。

超类init可以调用实例 在子类中重写的方法。那是(至少一个) 之所以必须在调用 super.init()之前初始化所有子类属性的原因。

一个简单的例子:

class Base
{
    init(){
        print("enter Base.init")
        setup()
        print("leave Base.init")
    }

    func setup() {
        print("Base.setup called")
    }
}

class Test : Base
{
    internal var y:Int
    override init()
    {
        y = 123
        print("before super.init")
        super.init()
        print("after super.init")
    }

    override func setup() {
        print("Test.setup called")
        print("y = \(y)")
    }
}

输出:

before super.init
enter Base.init
Test.setup called
y = 123
leave Base.init
after super.init

如您所见,访问子类的y属性 在super.init()通话期间,即使不知道 超类。

比较Objective-C中的情况可能会很有趣 始终首先调用self = [super initXXX]。这有 结果是init / dealloc方法中的属性访问self.prop 是不安全的,直接访问实例变量_prop 建议因为对象可能处于部分构造状态"。 请参阅示例Should I refer to self.property in the init method with ARC?

所以这是Swift已经解决的问题之一 (以更严格的要求为代价)。

答案 1 :(得分:3)

来自文档:

  

安全检查1
  指定的初始化程序必须确保所有的   其类引入的属性在委托之前初始化   一个超类初始化器。

     

如上所述,只考虑对象的内存   一旦所有存储属性的初始状态为,就初始化   众所周知。为了满足这条规则,指定   初始化程序必须确保初始化所有自己的属性   在把它放到链子之前。

来源:Swift Language Guide: Initialization

只需在init

中交换两行
override init()
{
    y = 123
    super.init()  
}