penangite
penangite

Reputation: 33

Swift: Difference between initializing superclass with a convenience initializer and a designated initializer

Let's say I have a class Dog declared as below:

class Dog {
    let variable1: String
    let variable2: Int

    init(variable1: String, variable2: Int) {
        self.variable1 = variable1
        self.variable2 = variable2
    }
}

And ChowChow is a subclass of Dog, deliberately declared empty as below:

class ChowChow: Dog {}

So let's assume now I wish to add an initializer to the subclass ChowChow.

My question is this: What is/are the difference(s), if any, between having a convenience initializer for subclass ChowChow:

class ChowChow: Dog {
    convenience init() {
        self.init(variable1: "value1", variable2: 2)
    }
}

and a designated initializer for subclass ChowChow?:

class ChowChow: Dog {
    init() {
        super.init(variable1: "value1", variable2: 2)
    }
}

Using the following test, I could see that the results are the same for either implementation:

let chowchow = ChowChow()
print(chowchow.variable1) // Prints "value1"
print(chowchow.variable2) // Prints "2"

Thanks in advance for shedding light!

Upvotes: 2

Views: 51

Answers (1)

MANIAK_dobrii
MANIAK_dobrii

Reputation: 6032

Regarding basic Swift 4.0- specifications the same differences between designated and convenience initializers apply as in any other case.

Points used here:

  • Convenience initializers must call other initializer and ultimately call designated initializer
  • Designated initializers must and may only call superclass initializers (if any)
  • By default subclasses do not inherit designated initializers from superclass. Assuming that you provide default values for any new properties you introduce in a subclass, if your subclass doesn’t define any designated initializers, it automatically inherits all of its superclass designated initializers. (see Automatic Initializer Inheritance)

In your example:

class ChowChow: Dog {
    convenience init() {
        self.init(variable1: "value1", variable2: 2)
    }
}

you did not introduce any designated initializers to ChowChow subclass thus, all the designated initializers from superclass are inherited (i.e. init(variable1:variable2)). Since convenience initializer must ultimately call designated initializer, you call inherited self.init(variable1: "value1", variable2: 2) from your convenience initializer, note self there.

In your second example:

class ChowChow: Dog {
    init() {
        super.init(variable1: "value1", variable2: 2)
    }
}

you introduce designated initializer init() to a subclass. By default designated initializers are not inherited in subclasses, unless some conditions are met (like in the first example). So, in this specific case subclass ChowChow has only one designated initializer init() and nothing else, since designated initializers must call designated initializers from superclass, you call superclass's super.init(variable1: "value1", variable2: 2), note super here.

For details see: Initializer Inheritance and Overriding

Upvotes: 1

Related Questions