initializer override

In the following code, why is the property of bacon.name equal to "[Unnamed]" if class RecipeIngredient overrides init(name:) and does not make a call to class Food's init() initializer? I'm having trouble tracing the flow of this code. Can anyone explain this to me?


class Food {

var name: String

init(name: String) {

self.name = name

}

convenience init() {

self.init(name: "[Unnamed]")

}

}


class RecipeIngredient: Food {

var quantity: Int

init(name: String, quantity: Int) {

self.quantity = quantity

super.init(name: name)

}

override convenience init(name: String) {

self.init(name: name, quantity: 1)

}

}


let bacon = RecipeIngredient()

print(bacon.name)

// prints "[Unnamed]"

print(bacon.quantity)

// prints "1"

Is this Apple's FoodTracker sample app?

You should probably look in the init inheritance rules:


https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html


It says:


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.


These rules apply even if your subclass adds further convenience initializers.


NOTE

A subclass can implement a superclass designated initializer as a subclass convenience initializer as part of satisfying rule 2.


Your override of 'init(name:)' means that you've overridden all of the superclass's designated initializers. In that case, you inherit the superclass's convenience initializers, just 'init()' in this case, even though you've added further convenience initialzers.

When you call RecipeIngredient() without any parameter, the init() of the superclass (Food) is called, because there is no init() in the RecipeInfgredient class.


This convenience init() calls self.init(name: String) with the name "Unnamed".


Hence the print : Unnamed


self.init(name: String) calls the convenience init(name: String) of RecipeIngredient (because self is of class RecipeIngredient) ; self.quantity is thus set to 1.


You can play with this and add your own init() in RecipeIngredient


    init() {
        self.quantity = 10
        super.init(name: "myRecipeIngredientInitName")
    }


This time, when you call RecipeIngredient() without any parameter, the init() of RecipeIngredient is called


Result is :

let bacon = RecipeIngredient()

print(bacon.name)

// "myRecipeIngredientInitName\n"

print(bacon.quantity)

// prints "10"

initializer override
 
 
Q