【问题标题】:objective-c init目标c初始化
【发布时间】:2025-12-17 12:45:01
【问题描述】:

对象分配后真的有必要调用init吗?我的意思是:例如,在 Java 中,如果您不调用它(构造函数),无论如何都会调用它(默认构造函数)。在 Objective C 中,您可以创建一个替代构造函数(如 Java),我看到最多的东西之一是 self = [super init]。我读到:cocoawithlove article,但最后不清楚我们为什么要进行这样的分配self = [super init]。它只是说[super init] 可以返回一个不同的对象,然后我们必须用那个新对象替换self。这无法解释为什么我们首先要这样做。

【问题讨论】:

  • 根据继承逻辑,可以重写超类的方法。如果你覆盖了 -init 方法,那么 super 的 -init 将永远不会被调用。您确保在新的-init 方法中手动调用该方法,它将初始化您的超类。如果你写了超类,如果你 100% 确定一切都会正常启动,你可以避免调用 super,但是当你对超类一无所知时,错过调用 super 的 -init 方法是非常危险,可能会导致某些私有变量无法初始化,并导致不良行为或崩溃。

标签: objective-c init


【解决方案1】:

对象分配后真的需要调用init吗?

是的,这是必要的。与 Java 相比,调用 [super init](或其他一些指定的初始化程序)有效地运行超类的构造函数。在 Java 中为您提供了这种机制,但在 Objective-C 中没有。所以它不像在 Java 中那样在 ObjC 中被隐式调用。在 ObjC 中,您必须显式调用超类的指定初始化程序之一。如果你不调用你的超类的初始化器,你的对象将不会被完全初始化。这可能不会导致任何副作用,也可能会导致调用未定义行为的完全不可用的对象。

为什么我们应该做这样的赋值 self = [super init]。

没错,alloc 创建了一个分配(内存归零)并设置了指向类信息isa 的指针,但是超类的初始化器允许超类与另一个可能更合适的交换实例。通常,您会避免在自己的子类中这样做。执行此操作和 nil 检查的另一个原因是它是处理错误的方法。在 ObjC 中,异常一般是不可恢复的,因此向子类报告错误的常规方式是返回nil。这就是为什么不仅分配self,而且测试nil也很重要。

【讨论】:

  • 但是从 alloc 返回的到底是什么? init(默认情况下)做什么使对象可用?当我调用 init 时,我假设默认行为是直到根类的调用链。会这样吗?
  • @BrunoBraga a) 认为它是calloc 的结果,其大小足以容纳实例。类的isa 已设置(例如,运行时用于标识类、访问其选择器等)。如果没有isa,对象将无法向上遍历层次结构。 b) 是的。由于 super 的 init 是(er -- 应该 )首先调用的,所以类是从基础构造的——就像在 Java 中一样。 NSObject 的 init 不需要做任何特别的事情,但它是你必须履行的契约。事实上,文档说它的 NSObject init 目前什么都不做 :)
【解决方案2】:

Objective C 和 Java 之间有很大的不同。 Java 是一种从头开始构建的解释性语言,而 Objective C 是建立在 C 语言之上的。你可以在 C 中做的任何事情在 Objective C 中也是有效的。

与 Java 不同,C(以及扩展的 Objective C)具有“原始内存分配”。在Java 中,对new 的调用自动 调用构造函数。该语言使绕过这种机制成为不可能。然而,在 Objective C 中,您可以分配原始内存。在从alloc 返回给您时,内存中不包含随时可用的对象 - 它只是部分准备好使用。内存块有一个引用计数,它提供了足够的空间来容纳你的对象,但它还没有准备好接收你自己的子类已经实现的消息。这就是为什么你必须调用init(或使用new,它结合了allocinit)。

if (self = [super init]) 分配/检查可让您在对象的构造阶段捕获错误。如果您自己的初始化程序失败,您可以设置self = nil 来报告链上的问题。分配不同的对象要少得多,但也可以这样做。

【讨论】:

    【解决方案3】:

    分配后实例变量应该被实例化。 self = [super init]是指初始化超类的init方法

    一个常见的错误是写

    self = [[super alloc] init]; 它返回超类的一个实例,这不是您在子类构造函数/init 中想要的。你得到一个不响应子类方法的对象,这可能会令人困惑,并会产生关于不响应方法或未找到标识符等令人困惑的错误。

    self = [super init] 如果超类有成员(变量或其他对象)在设置子类的成员之前首先初始化,则需要。否则,objc 运行时会将它们全部初始化为 0 或 nil。 (不像 ANSI C,它经常分配内存块而不清除它们)

    是的,由于内存不足错误、缺少组件、资源获取失败等原因,基类初始化可能会失败,因此检查 nil 是明智的,并且只需不到几毫秒。

    【讨论】: