非指定初始化程序可以调用父类的指定初始化程序吗?

3
以下内容是否可行?
1)非指定初始化程序是否可以调用超类的指定初始化程序 2)类的指定初始化器是否可以调用超类的非指定初始化器?
或者必须遵循以下流程: a)指定初始化程序必须调用超类的指定初始化程序 b)非指定初始化程序必须调用自己类的指定初始化程序
如果违反了上述(1)或(2),会发生什么?(或者,如果我们必须始终遵循(a)和(b),那么背后的原因是什么?)
3个回答

3
  • 1:不可以。
  • 2:可以。
  • a:有争议。
  • b:可以。

指定初始化程序的意义在于它是那个初始化程序,知道如何正确地设置正在处理的对象。类中的所有其他初始化程序都应调用指定初始化程序;如果它们没有这样做,则对象可能未被正确初始化。

苹果的Cocoa文档讨论了如何处理多个初始值设定项,其中包括以下内容:

一个类的初始化参数完整时,其初始化程序通常是指定初始化程序。字类的指定初始化程序必须通过向super发送消息来调用其超类的指定初始化程序。

这听起来有点含糊不清--它听起来像是子类的指定初始化程序必须调用其超类的指定初始化程序。但我认为这不是真正的意图。这里的真正意图是指定初始化程序负责通过发送消息到super确保超类已经正确初始化。如果您恰好通过调用super的非指定初始化程序来完成这一点,那应该没有问题,只要该初始化程序最终导致调用指定初始化程序即可。因此,我不认为(2)是一个问题。

继续阅读我们有:

方便(或辅助)初始化程序--其中可以包括init--不调用super。

所以他们在这里说的一个重要区别在于,指定的初始化程序是唯一一个向super发送初始化消息的程序。

回到(1),如果您有一个“非指定”的初始化程序,该程序调用[super init],那么这并不是真正的非指定初始化程序。通过向super发送初始化消息,您的方法正在承担指定初始化程序的责任。这不一定是一个问题--请注意,UIView有两个指定的初始化程序--但它打破了通常的约定,因此您应该有一个非常好的理由来这样做。


2
由于创建指定初始化器并不是正式的,因此由你违反规则。
对于具有多个初始化器的类,常见的做法是将接受最多参数的初始化器作为指定初始化器,并让所有其他初始化器调用它。只有指定初始化器可以调用超类的指定初始化器,其遵循相同的规则。
如果其他人子类化您的类并调用指定的初始化器,则他们确保所有实例变量都已正确初始化。如果您的类不遵循这些通用惯例,则可能会为自己创建一个混乱的类,并使其更难以供其他人使用。

-1
以下事情能做到吗?
1)非指定初始化程序调用超类的指定初始化程序
实际上必须这样做,因为作为子类实现者,您无法知道超类指定初始化程序中有什么代码并自行实现它而不拥有该代码。您没有其他合理的方法来初始化超类。
无论您是子类还是外部客户端,都必须调用指定的初始化程序。上述引用的文档是不正确的。
2)类的指定初始化程序调用超类的非指定初始化程序?
如果超类提供了非指定初始化程序并实现了调用指定初始化程序,则在父级上调用任何初始化程序绝对没有问题。
以前的答案似乎让您基本上在没有代码的情况下在自己的代码中实现所有超类构造函数。错误。这就是为什么超类初始化程序存在的原因,以便您可以安全地扩展它们而不必拥有该代码。

你的回答的第一部分是错误的:指定初始化器的定义就是所有其他初始化器必须调用的方法。如果指定初始化器是-initWithRed:green:blue:,那么-init将调用[self initWithRed:... green:... blue:...]。指定初始化器是你放置类所需初始化代码的地方,其他初始化器必须调用它以便执行该代码。指定初始化器有责任调用其中一个超类的初始化器。我不理解你最后一段的意思,但如果你是在引用我的回答,也许你可以在那里发表评论。 - Caleb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接