指定初始化程序,请澄清。

时间:2015-08-29 23:40:50

标签: objective-c initialization subclass init designated-initializer

现在我已经把这个问题蒙上阴影了很长一段时间,我真的需要有人为我澄清这一点。

1)当子类化的init方法调用它时,编译器如何确定指定的初始化方法?因为它被认为是覆盖面最广的那个。

2)当使用多个init方法进行子类化时,每个类是否都有自己指定的初始化方法?对问题2的回答也会增加对理解这一点的帮助。

3)当多个类确实有一个指定的初始化程序时,其他init方法如何在其类中调用指定的初始值设定项?为什么他们也不调用任何其他初始化器?为什么指定初始化器?什么特别的呢?

2 个答案:

答案 0 :(得分:2)

  1. 编译器无法以任何方式检测到它。为了让编译器知道是否指定了初始值设定项,您必须使用NS_DESIGNATED_INITIALIZER宏对其进行声明。

  2. 如果一个类有一个初始化器,它总是有一个指定的初始化器。它实际上可以有多个指定的初始化器。如果没有指定的初始化程序,您就无法拥有一个类。指定和便利之间的区别非常简单。指定的初始化程序调用{​​{1}}(调用超类初始化程序),同时方便调用[super init...](调用同一类的另一个初始化程序)。

  3. 便利初始化程序使用[self init...]调用指定的程序。指定的初始化程序并不特殊。它们实际上是最基本的初始化器。他们做两件事 - 他们初始化父母(使用[self init...]),然后初始化所需的东西(例如属性的默认值等)。便利初始化器是特殊类型 - 它们是指定初始化器的扩展。他们调用指定的初始化程序并执行更多操作。例如,[super init...]将是一个指定的初始化程序,它将对象初始化为特定样式。 -initWithStyle:也会这样做,但它也会将-initWithStyle:andFrame:属性设置为特定值。如果frame使用-initWithStyle:andFrame:实施,那么它就是一个便利初始化程序。

答案 1 :(得分:2)

在Objective-C中,类的指定初始值设定项是负责正确初始化类以使其处于适当状态以供使用的方法。代码中没有任何内容将其标记为指定的初始值设定项,因此头文件中通常会有注释。由开发人员使用或扩展该类以确定哪个方法是指定的初始化程序(通常为init或以init为前缀)并相应地编写代码。如果没有正确记录并且其源代码不可用,这可能导致错误使用类,这是Swift试图解决的缺点之一。所以要解决你的问题...

  1. 指定的初始化程序不是由编译器确定的。子类还应该有一个指定的初始值设定项,可以在某个时刻调用超级指定的初始值设定项。
  2. 每个类应明确说明(通过注释或文档)哪个初始化程序用作指定的初始化程序。由使用该类的开发人员来确保调用指定的初始化程序。由类本身的开发人员来确保按预期调用超级指定的初始化程序。但是,通过正确编写的类,任何init方法都应该调用指定的初始化程序。但是,编译器无法保证。
  3. 需要对其他init方法进行适当编码,以通过[self init...][super init...]调用指定的初始值设定项。同样,您需要弄清楚如何使用类以及如何使用它或对其进行适当扩展。
  4. 指定的初始化程序是执行"繁重提升的方法。准备一个新的类实例供使用。其他初始化程序称为便捷初始化程序,通常用于提供隐含默认值的较短签名,因为您无法为Objective-C方法签名指定默认参数值。

    在大多数情况下,如果一个类被正确编写,你不应该太担心,因为所有的便利初始化器最终都应该调用指定的类。

    在Swift的开发过程中已经考虑了很多想法,即使你不打算学习它,你应该阅读Swift Initializers因为它会让你很好地了解正确的初始链,您可以使用它来指导您在Objective-C中创建初始值设定项。

    更新: 从Xcode 6开始,指定的初始值设定项可以通过NS_DESIGNATED_INITIALIZER宏标记。这有助于强制执行正确编写的类,并且是从Swift返回到Objective-C的东西。查看iOS Designated Initializers : Using NS_DESIGNATED_INITIALIZER