kerry
kerry

Reputation: 2582

Swift Initializer Mystery

Few blocks of code:

This works:

import Foundation

class Class1 {
    init(param1: String?) {
        print("hello")
    }

    convenience init() {
        self.init(param1: nil)
    }
}

class SubClass1: Class1 {

}

let obj = SubClass1()

In the above code, the designated initialiser is passed down to SubClass1 because SubClass1 does not provide its own designated initialiser. Also, convenience initialiser is also passed down. Therefore, this works.

import Foundation

class Class1 {
    init(param1: String?) {
        print("hello")
    }

    convenience init() {
        self.init(param1: nil)
    }
}

class SubClass1: Class1 {
    override init(param1: String?) {
        print("hello 2")
        super.init(param1: nil)
    }
}

let obj = SubClass1()

This works too because SubClass1 has provided its own designated initialiser now.

import Foundation

class Class1 {
    init(param1: String?) {
        print("hello")
    }

    init(param2: String?) {
        print("world")
    }

    convenience init() {
        self.init(param1: nil)
    }
}

class SubClass1: Class1 {
    override init(param1: String?) {
        print("hello 2")
        super.init(param1: nil)
    }
}

let obj = SubClass1()

This gives "error: missing argument for parameter 'param1' in call" for the last line. Here, there is a designated initialiser for SubClass1 and convenience initialiser from parent also calls the same initialiser, then why the error?

This

import Foundation

class Class1 {
    init(param1: String?) {
        print("hello")
    }

    required init(param2: String?) {
        print("world")
    }

    convenience init() {
        self.init(param1: nil)
    }
}

class SubClass1: Class1 {
    override init(param1: String?) {
        print("hello 2")
        super.init(param1: nil)
    }

    required init(param2: String?) {
        print("world")
        super.init(param2: nil)
    }
}

let obj = SubClass1()

and this works:

import Foundation

class Class1 {
    init(param1: String?) {
        print("hello")
    }

    init(param2: String?) {
        print("world")
    }

    convenience init() {
        self.init(param1: nil)
    }
}

class SubClass1: Class1 {
    override init(param1: String?) {
        print("hello 2")
        super.init(param1: nil)
    }

    override init(param2: String?) {
        print("world")
        super.init(param2: nil)
    }
}

let obj = SubClass1()

Why does it need all the designated initialisers to be overridden for the one convenience initialiser to work that calls just one of the designated initialisers?

Upvotes: 3

Views: 99

Answers (1)

Sweeper
Sweeper

Reputation: 271420

This behaviour is clearly stated in the swift guide.

Assuming that you provide default values for any new properties you introduce in a subclass, the following two rules apply:

Rule 1 If your subclass doesn’t define any designated initializers, it automatically inherits all of its superclass designated initializers.

Rule 2 If your subclass provides an implementation of all of its superclass designated initializers—either by inheriting them as per rule 1, or by providing a custom implementation as part of its definition—then it automatically inherits all of the superclass convenience initializers.

So basically, your subclass must override/define all of the superclass' designated initialisers to get the superclass' convenience initialisers inherited.

Upvotes: 1

Related Questions