Inherited convenience initializer - 为什么它有效?

Inherited convenience initializer - why does this work?

我有下面的例子和一个问题:
我知道在某些情况下初始化程序是继承的。

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 mystery = RecipeIngredient()  // Why does this work?

我原以为没有任何参数的初始化不起作用,因为便利初始化器仅在基 class 中声明并且没有设置数量 属性.
显然它无论如何都有效。但为什么?当我在没有任何参数的情况下调用(至少在子 class 不存在的)初始化程序时,后台会发生什么?

子 class 中定义了初始化器,并且从超级 class 中定义了初始化器(当然除非它们中的任何一个在子 class 中被覆盖)。所以在这种情况下 RecipeIngredient

有 3 个初始化

来自RecipeIngredient

init(name: String, quantity: Int){
    self.quantity = quantity
    super.init(name: name)
}

override convenience init(name: String){
    self.init(name: name, quantity: 1)
}

还有一个来自 Food

convenience init() {
    self.init(name: "[unnamed]")
}

现在便利 init 必须直接或通过另一个便利 init 调用默认 init,所以这里的调用链变成了

Food.init() -> RecipeIngredient.init(name:) -> RecipeIngredient(name:quantity) -> Food.init(name:)

这可以通过将 print(#function) 添加到每个 init 来很容易地看到,它给出

的输出
let mystery = RecipeIngredient() 

init()
init(name:)
init(name:quantity:)
init(name:)