An issue about Initialization code

class Food {
    var name: String
    init(name: String) {
        self.name = name
    }
    
    convenience init() {
        self.init(name: "[unanmed]")
    }
}


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 oneMysteryItem = RecipeIngredient()
let oneBacon = RecipeIngredient(name: "Bacon")
let sixEggs = RecipeIngredient(name: "Eggs", quantity: 6)

These codes appear at page: Documentation

I'm learning Initialization unit, I think "let oneMysteryItem = RecipeIngredient()" this sentence is strange...Thx.

Can you elaborate on why you feel it is strange?

PS: you can make it easier for others to read your code by pretty-formatting the code, by pasting it between a pair three back-tick characters ``` as shown below.

```
Paste code here
```

For example:

// Approximate PI
let PI = 22.0 / 7.0
1 Like

To understand what's going on it can be useful to add print statements in each init, logging calls. So for this "mystery item" it will have the following initialisation order:

convenience Food.init()
convenience RecipeIngredient.init(name:)
RecipeIngredient.init(name:quantity:)
Food.init(name:)

As you can see, it goes first to the parent class convenience initializer. Which in order calls init(name:), but there are two such initializers: in parent class and overriden in child (marked as convenience to be able to use designated class initializer). It correctly resolves to use child implementation, as we initialize child class. This initializer calls designated init(name:quantity) on RecipeIngredient, initializing added property, and finally calls parent init(name:) to complete object initialization.

1 Like

ok

1 Like

Thanks.

In the RecipeIngredient class does not define a designated initializer without parameters (i.e., no init()). So I wonder if "let oneMysteryItem = RecipeIngredient()" would cause an error?

This does sound a bit off indeed as if you are "overriding a convenience initialiser" while in fact you are overriding a designated initialiser and just marking your override with "convenience" (e.g. because you want to call another initialiser via self instead of via super. FWIW both spelling compile fine: "override convenience init" and "convenience override init".

True, Swift won't know how to initialise then.

I’m not sure I get your question… The code example doesn’t have a designated initializer without parameters, only convenience one.

If RecipeIngredient type didn’t have overridden init(name:), than you’d get an error, as Swift wouldn’t know how to initialize all the properties on the type. But as long as there is a path to call a finite set of initializers on child and parent types, that initialize all the properties, it is fine.

“ Even though RecipeIngredient provides the init(name: String) initializer as a convenience initializer, RecipeIngredient has nonetheless provided an implementation of all of its superclass’s designated initializers. Therefore, RecipeIngredient automatically inherits all of its superclass’s convenience initializers too.”

Finally, I can understand this sentence.