Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the purpose of initializing property values before calling super designated initializer in swift?

Tags:

swift

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.

like image 734
AntiMoron Avatar asked Dec 16 '15 08:12

AntiMoron


People also ask

Why do we need initialization in Swift?

Swift init() Initialization is the process of preparing an instance of a class, structure, or enumeration for use. This process involves setting an initial value for each stored property on that instance and performing any other setup or initialization that is required before the new instance is ready for use.

Why do we need convenience initializer of the same task can be obtained with designated initializer?

A convenience initializer is a secondary initializer that must call a designated initializer of the same class. It is useful when you want to provide default values or other custom setup. A class does not require convenience initializers.

Which type of property is initialized when it is accessed first in Swift?

Example: Swift Initializer Inside the initializer, we have initialized the value of the length property. Here, when the wall1 object is created, the init() initializer is called.

Why do we use initialization?

Initialization is the process of locating and using the defined values for variable data that is used by a computer program. For example, an operating system or application program is installed with default or user-specified values that determine certain aspects of how the system or program is to function.


1 Answers

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).

like image 195
Martin R Avatar answered Nov 15 '22 11:11

Martin R