Reputation: 5801
The Swift documentation says,
"You can override a failable initializer with a nonfailable initializer but not the other way around."
Can somebody explain why a nonfailable initialiser cannot be overriden by a failable initializer ?
Upvotes: 0
Views: 118
Reputation: 154523
A failable initializer returns an optional value. If you override that with a nonfailable initializer, you are returning a non-optional value and the compiler just wraps it in an optional. The other way around doesn't work. What is the compiler to do when your overriden initializer returns nil
? How does it map that into an initializer that doesn't return an optional?
I was under the impression that when you override a failable initializer with a non failable initializer returned value is non optional , So it didn't make any sense.
Well, it does return a non-optional if you call the init
on the overriding class. To see the optional return, you need to trick Swift into calling init
on the base class.
How do you do that? Here is a way:
class Foo {
var x: Int
required init?() {
x = 4
}
}
class Bar : Foo {
// required includes override automatically
required init() {
super.init()!
x = 5
}
}
let bar1 = (Bar.self).init() // this is equivalent to Bar()
let bar2 = (Bar.self as Foo.Type).init()
print(type(of: bar1)) // Bar
print(type(of: bar2)) // Optional<Foo>
print(type(of: bar2!)) // Bar
print(bar1.x) // 5
print(bar2!.x) // 5
Notice: (Bar.self as Foo.Type).init()
returned an optional even though it was created with the non-failable Bar
initializer.
Note: I had to add required
to make this work, and required
is an automatic override
. If you make Foo
's init non-failable and Bar
's init failable you will see the error message Failable initializer 'init()' cannot override a non-failable initializer
Upvotes: 2