rustylepord
rustylepord

Reputation: 5801

Swift Initializers

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

Answers (1)

vacawama
vacawama

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

Related Questions