可以完成以下操作吗?
1)非指定初始化程序调用超类的指定初始化程序
2)一个类的指定初始化程序调用超类的非指定初始化程序?
或者必须是:
a)指定的初始化程序必须调用超类的指定初始化程序
b)非指定初始值设定项必须调用自己类的指定初始化程序
如果违反上述(1)或(2),会发生什么? (或者,如果我们必须始终遵循(a)和(b),背后的原因是什么?)
答案 0 :(得分:3)
指定初始化程序的要点是初始化程序知道如何正确设置手头的对象。该类中的所有其他初始值设定项应调用指定的初始值设定项;如果他们不这样做,该对象可能无法正确初始化。
Apple的Cocoa文档讨论how to handle multiple initializers,其中包括以下内容:
一个完整补充的类的初始化器 初始化参数通常是指定的初始化程序。该 子类的指定初始值设定项必须调用指定的 通过向super发送消息来实现其超类的初始化。
这有点模棱两可 - 听起来像子类的指定初始值设定项必须调用其超类的指定初始值设定项。但我认为这不是真正的意图。这里的真正要点是指定的初始化者有责任通过向super
发送消息来确保正确初始化超类。如果您碰巧通过调用super
的一个非指定初始化程序来执行此操作,那么该初始化程序最终会导致调用指定的初始化程序,这应该没问题。因此,我不相信(2)是一个问题。
进一步阅读我们:
方便(或次要)初始化程序 - 可以包括init-不要调用super。
所以他们在这里说的是指定的初始化器和任何其他初始化器之间的一个重要区别是指定的初始化器是唯一一个向super
发送初始化消息的初始化器。
回到(1),如果你有一个调用[super init]
的“非指定”初始值设定项,那它就不是一个非指定的初始化程序。您的方法通过向super
发送初始化消息来承担指定初始值设定项的责任。这不是必然一个问题 - 请注意UIView有两个指定的初始值设定项 - 但它违反了通常的约定,所以你应该有充分的理由这样做。
答案 1 :(得分:2)
由于创建指定的初始化程序不正式,因此您可以违反规则。
具有多个初始化程序的类的常见做法是使接受最多参数的接收器成为指定的初始化程序,并让所有其他初始化程序调用它。只有指定的初始化程序才能调用超类的指定初始化程序,它遵循相同的规则。
如果其他人将您的类子类化并调用指定的初始值设定项,则可以确保所有实例变量都已正确初始化。如果你的班级不遵循这些常规做法,你可以为自己创建一个凌乱的课程,但要让其他人使用它更难。
答案 2 :(得分:-1)
可以完成以下操作吗?
1)非指定的初始化程序调用指定的超类 初始化
实际上必须才能完成,因为作为子类实现者无法知道超类指定初始化程序中的代码并自己实现它而不需要代码。你没有其他合理的方法来启动超类。
无论您是子类还是外部客户端,都必须调用指定的初始化程序。上面引用的文档不正确。
2)一个类的指定初始化程序调用超类 非指定的初始化程序?
如果超级提供了非指定的初始值设定项并且实现了调用指定的初始化程序,那么在父级调用任何初始化程序时绝对没有问题。
之前的答案似乎是你必须在你自己的代码中基本实现所有超类构造函数而不需要代码。错误。这就是为什么存在超类初始化器,以便您可以安全地扩展它们而无需使用代码。