init
对象分配后真的有必要调用吗?我的意思是:例如,在 Java 中,如果您不调用它(构造函数),无论如何都会调用它(默认构造函数)。在 Objective C 中,您可以创建一个替代构造函数(如 Java),而我看到最多的东西之一是self = [super init]
. 我读过:cocoawithlove 文章,但最后不清楚我们为什么要进行这样的分配self = [super init]
。它只是说[super init]
可以返回一个不同的对象,然后我们必须self
用那个新对象替换 。这无法解释为什么我们首先要这样做。
3 回答
对象分配后真的有必要调用init吗?
是的,这是必要的。为了与 Java 进行比较,调用[super init]
(或其他一些指定的初始化程序)有效地运行超类的构造函数。在 Java 中为您提供了这种机制,但在 Objective-C 中没有。所以它不像在 Java 中那样在 ObjC 中被隐式调用。在 ObjC 中,您必须显式调用超类的指定初始化程序之一。如果你不调用你的超类的初始化器,你的对象将不会被完全初始化。这可能不会导致任何副作用,或者可能会导致调用未定义行为的完全不可用的对象。
为什么我们应该做这样的赋值 self = [super init]。
对,alloc
创建一个分配(内存归零)并设置指向类信息的指针isa
,但是超类的初始化器允许超类与另一个可能更合适的交换实例。通常,您会避免在自己的子类中这样做。执行此操作和 nil 检查的另一个原因是它是处理错误的方法。在 ObjC 中,异常一般是不可恢复的,因此向子类报告错误的常规方式是 return nil
。这就是为什么不仅分配self
,而且测试它也很重要nil
。
Objective C 和 Java 之间有很大的不同。Java 是一种从头开始构建的解释性语言,而 Objective C 是建立在 C 语言之上的。你可以在 C 中做的任何事情在 Objective C 中也是有效的。
与 Java 不同,C(以及扩展的 Objective C)具有“原始内存分配”。在 Java 中,调用会new
自动调用构造函数。该语言使绕过这种机制成为不可能。然而,在 Objective C 中,您可以分配原始内存。内存在返回给您时不包含随时可用的对象alloc
- 它只是部分准备好使用。内存块有一个引用计数,它提供了足够的空间来容纳你的对象,但它还没有准备好接收你自己的子类已经实现的消息。这就是为什么您必须调用init
(或使用new
,它结合了alloc
和init
)。
if (self = [super init])
分配/检查使您可以在对象的构造阶段捕获错误。如果您自己的初始化程序失败,您可以设置self = nil
为向上报告问题。分配不同的对象要少得多,但也可以这样做。
分配后实例变量应该被实例化。
self = [super init]
指初始化超类init方法
一个常见的错误是写
self = [[super alloc] init];
它返回超类的实例,这不是您在子类构造函数/init 中想要的。你得到一个不响应子类方法的对象,这可能会令人困惑,并会产生关于不响应方法或未找到标识符等的令人困惑的错误。
self = [super init]
如果超类有成员(变量或其他对象)在设置子类的成员之前首先初始化,则需要。否则,objc 运行时会将它们全部初始化为 0 或 nil。(不像 ANSI C,它经常分配内存块而不清除它们)
是的,基类初始化可能会由于内存不足错误、缺少组件、资源获取失败等而失败,因此检查 nil 是明智的,并且只需不到几毫秒。