7

Here is my code:

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
    }
}

I think this should be compiled:

y is not visible inside class 'Base',whether order of initializations of y's and super class's doesn't really matter.

AntiMoron
  • 1,286
  • 1
  • 11
  • 29

2 Answers2

11

Your argument

I think this should be compiled:

y is not visible inside class 'Base',whether order of initializations of y's and super class's doesn't really matter.

is not correct, that would not be safe.

The superclass init can call an instance method which is overridden in the subclass. That is (at least one) reason why all subclass properties must be initialized before super.init() is called.

A simple example:

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)")
    }
}

Output:

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

As you can see, the y property of the subclass is accessed during the super.init() call, even if it is not known to the superclass.


It might be interesting to compare the situation in Objective-C where self = [super initXXX] is always called first. This has the consequence that property access self.prop in init/dealloc methods is unsafe and direct access to the instance variable _prop is recommended because the object may be in a "partially constructed state". See for example Should I refer to self.property in the init method with ARC?.

So this is one of the issues which have been solved in Swift (at the cost of stricter requirements).

Community
  • 1
  • 1
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • I think there is a difference in level of "unsafeness" between the partially constructed state situation in Objective-C and Swift. In Objective-C (Apple runtime), every instance variable is automatically initialized to a known value, the zero value of the type, which exists for every type. So accessing partially constructed state is still at least well defined, though it may break the programmer's assumptions. But in Swift, not all types have a "zero value" (particularly, non-optional object references), so accessing a partially constructed state could result in an impossible situation. – newacct Dec 19 '15 at 02:11
  • thanks for your answer, it has been confused me a lot. – Seth Jun 07 '16 at 10:42
3

From the documentation:

Safety check 1
A designated initializer must ensure that all of the properties introduced by its class are initialized before it delegates up to a superclass initializer.

As mentioned above, the memory for an object is only considered fully initialized once the initial state of all of its stored properties is known. In order for this rule to be satisfied, a designated initializer must make sure that all its own properties are initialized before it hands off up the chain.

Source: Swift Language Guide: Initialization

Just exchange the two lines in init

override init()
{
    y = 123
    super.init()  
}
vadian
  • 274,689
  • 30
  • 353
  • 361