Reputation: 1366
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.
Upvotes: 7
Views: 779
Reputation: 539835
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).
Upvotes: 11
Reputation: 285082
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()
}
Upvotes: 3