指定的初始化程序,请澄清。
Designated Initializer, clarify please.
现在这个问题困扰了我很长一段时间,我真的需要有人为我澄清这个问题。
1) 当被子classed 初始化方法调用时,编译器如何确定指定的初始化方法?因为它据说是覆盖率最高的。
2) 当 subclass 使用多个初始化方法时,每个 class 是否都有自己指定的初始化方法?回答问题 2 也有助于理解这一点。
3) 当多个 class 确实有一个指定的初始化器时,其他初始化方法如何在它们的 class 中调用指定的初始化器?为什么他们也不调用任何其他初始化程序?为什么要指定初始化程序?它有什么特别之处?
编译器没有以任何方式检测到它。为了让编译器知道是否指定了初始化程序,您必须使用 NS_DESIGNATED_INITIALIZER
宏对其进行注解。
如果 class 有一个初始化器,它总是也有一个指定的初始化器。它实际上可以有多个指定的初始值设定项。如果没有指定的初始值设定项,您根本无法拥有 class 。指定和方便之间的区别非常简单。指定初始化器调用 [super init...]
(调用超级class 初始化器),而方便调用 [self init...]
(调用相同 class 的另一个初始化器)。
便利初始化程序使用 [self init...]
调用指定的初始化程序。指定的初始值设定项并不特殊。它们实际上是最基本的初始化器。他们做了两件事 - 他们初始化父级(使用 [super init...]
)然后初始化需要的东西(例如属性的默认值等)。便利初始化器是一种特殊的——它们是指定初始化器的扩展。他们调用指定的初始化器并做更多的事情。例如 -initWithStyle:
将是一个指定的初始化器,它将一个对象初始化为特定的样式。 -initWithStyle:andFrame:
会做同样的事情,但它还会将 frame
属性 设置为特定值。如果 -initWithStyle:andFrame:
是使用 [self initWithStyle:... andFrame:...]
实现的,那么它是一个方便的初始化程序。
在 Objective-C 中,class 的指定初始化程序是负责正确初始化 class 以将其置于适当状态以供使用的方法。代码中没有任何内容将其标记为指定的初始值设定项,因此通常在头文件中对此进行注释。由使用或扩展 class 的开发人员来确定哪个方法是指定的初始化程序(通常是 init
或以 init
为前缀)并相应地编写代码。如果 class 没有正确记录并且其源代码不可用,这可能会导致误用 class,这也是 Swift 试图解决的缺点之一。因此,为了解决您的问题...
- 指定的初始值设定项不是由编译器确定的。一个 subclass 也应该有一个指定的初始化器,它在某个时候调用 super 的指定初始化器。
- 每个 class 都应该清楚地说明(通过注释或文档)哪个初始化程序打算用作指定的初始化程序。由使用 class 的开发人员来确保调用指定的初始化程序。由 class 本身的开发人员来确保按预期调用 super 的指定初始化程序。但是,如果 classes 编写得当,任何初始化方法 应该 调用指定的初始化程序。但是,编译器不保证。
- 其他 init 方法需要适当编码以通过
[self init...]
或 [super init...]
调用指定的初始化程序。同样,由您决定如何使用 class 并适当地使用或扩展它。
指定初始化器是执行 "heavy lifting" 以准备 class 的新实例以供使用的方法。其他初始化程序称为便利初始化程序,通常用于提供较短的签名和隐含的默认值,因为您不能为 Objective-C 方法签名指定默认参数值。
在大多数情况下,如果 class 写得正确,您真的不必太担心,因为所有便利初始化器最终都应该调用指定的初始化器。
在 Swift 的开发过程中对此进行了很多思考,即使您不打算学习它,也应该继续阅读 Swift Initializers,因为它会给您带来好处深入了解正确的初始化链,然后您可以使用它来指导您在 Objective-C.
中创建初始化程序
更新:
从 Xcode 6 开始,指定的初始值设定项可以这样标记,通常是通过 NS_DESIGNATED_INITIALIZER
宏。这有助于强制执行正确编写的 classes,并且是从 Swift 带回到 Objective-C 的东西。查看 iOS Designated Initializers : Using NS_DESIGNATED_INITIALIZER。
现在这个问题困扰了我很长一段时间,我真的需要有人为我澄清这个问题。
1) 当被子classed 初始化方法调用时,编译器如何确定指定的初始化方法?因为它据说是覆盖率最高的。
2) 当 subclass 使用多个初始化方法时,每个 class 是否都有自己指定的初始化方法?回答问题 2 也有助于理解这一点。
3) 当多个 class 确实有一个指定的初始化器时,其他初始化方法如何在它们的 class 中调用指定的初始化器?为什么他们也不调用任何其他初始化程序?为什么要指定初始化程序?它有什么特别之处?
编译器没有以任何方式检测到它。为了让编译器知道是否指定了初始化程序,您必须使用
NS_DESIGNATED_INITIALIZER
宏对其进行注解。如果 class 有一个初始化器,它总是也有一个指定的初始化器。它实际上可以有多个指定的初始值设定项。如果没有指定的初始值设定项,您根本无法拥有 class 。指定和方便之间的区别非常简单。指定初始化器调用
[super init...]
(调用超级class 初始化器),而方便调用[self init...]
(调用相同 class 的另一个初始化器)。便利初始化程序使用
[self init...]
调用指定的初始化程序。指定的初始值设定项并不特殊。它们实际上是最基本的初始化器。他们做了两件事 - 他们初始化父级(使用[super init...]
)然后初始化需要的东西(例如属性的默认值等)。便利初始化器是一种特殊的——它们是指定初始化器的扩展。他们调用指定的初始化器并做更多的事情。例如-initWithStyle:
将是一个指定的初始化器,它将一个对象初始化为特定的样式。-initWithStyle:andFrame:
会做同样的事情,但它还会将frame
属性 设置为特定值。如果-initWithStyle:andFrame:
是使用[self initWithStyle:... andFrame:...]
实现的,那么它是一个方便的初始化程序。
在 Objective-C 中,class 的指定初始化程序是负责正确初始化 class 以将其置于适当状态以供使用的方法。代码中没有任何内容将其标记为指定的初始值设定项,因此通常在头文件中对此进行注释。由使用或扩展 class 的开发人员来确定哪个方法是指定的初始化程序(通常是 init
或以 init
为前缀)并相应地编写代码。如果 class 没有正确记录并且其源代码不可用,这可能会导致误用 class,这也是 Swift 试图解决的缺点之一。因此,为了解决您的问题...
- 指定的初始值设定项不是由编译器确定的。一个 subclass 也应该有一个指定的初始化器,它在某个时候调用 super 的指定初始化器。
- 每个 class 都应该清楚地说明(通过注释或文档)哪个初始化程序打算用作指定的初始化程序。由使用 class 的开发人员来确保调用指定的初始化程序。由 class 本身的开发人员来确保按预期调用 super 的指定初始化程序。但是,如果 classes 编写得当,任何初始化方法 应该 调用指定的初始化程序。但是,编译器不保证。
- 其他 init 方法需要适当编码以通过
[self init...]
或[super init...]
调用指定的初始化程序。同样,由您决定如何使用 class 并适当地使用或扩展它。
指定初始化器是执行 "heavy lifting" 以准备 class 的新实例以供使用的方法。其他初始化程序称为便利初始化程序,通常用于提供较短的签名和隐含的默认值,因为您不能为 Objective-C 方法签名指定默认参数值。
在大多数情况下,如果 class 写得正确,您真的不必太担心,因为所有便利初始化器最终都应该调用指定的初始化器。
在 Swift 的开发过程中对此进行了很多思考,即使您不打算学习它,也应该继续阅读 Swift Initializers,因为它会给您带来好处深入了解正确的初始化链,然后您可以使用它来指导您在 Objective-C.
中创建初始化程序更新:
从 Xcode 6 开始,指定的初始值设定项可以这样标记,通常是通过 NS_DESIGNATED_INITIALIZER
宏。这有助于强制执行正确编写的 classes,并且是从 Swift 带回到 Objective-C 的东西。查看 iOS Designated Initializers : Using NS_DESIGNATED_INITIALIZER。