【问题标题】:In Objective-C why is id used as return type for init methods?在 Objective-C 中,为什么将 id 用作 init 方法的返回类型?
【发布时间】:2011-12-23 06:27:36
【问题描述】:

我做了一些快速搜索,但找不到答案。

我很想知道为什么在 Objective-C 中,id 被用作 init 方法的返回类型。

我的猜测是这是因为如果类被覆盖,您不想返回超类类型的对象,但我很想知道它是否出于其他原因。

【问题讨论】:

  • 尊敬的人大约 7 小时前否决了这个问题,如果你要否决一个问题,根据赞成和收藏的数量,显然有助于多人理解 Objective-C ,包括我自己的,至少添加评论为什么......

标签: objective-c


【解决方案1】:

是的。你的想法在金钱上是对的。子类应该仍然能够使用其父类的初始化方法并返回它自己的类型而不是父类型,并且返回id 允许它这样做。

【讨论】:

【解决方案2】:

超类类型的想法虽然是一个很好的理论,但并不能真正站得住脚:NSString *NSObject *。没有理由不能这样称呼它。

相反,我认为它更多地与函数签名有关。在像 Objective-C 这样的动态语言中,你可能不知道你在传递什么类。但是编译器必须知道返回的是什么类型。这和 Objective-C 的基于约定的编程历史(而不是有严格的规则)意味着您的子类可以init。这很古怪,但有效。

C++也有类似的问题,见Is the return type part of the function signature?

所以我们需要一个签名为-(id)init 的所有方法的单一类型,而id 是唯一有意义的东西,因为它只指定返回类型是一个实例。这足以让编译器做正确的事情。现在我们有了instancetype,它与正在发送消息的类匹配。

【讨论】:

  • 谢谢。对不起这里的死灵法;由于相关侧边栏,我来到这里。 :)
  • 别担心,我们总是欢迎额外的见解。出于好奇,我发布了这个问题。
  • 不,您可能希望返回子类,但不要编写自己的 init 方法(您正在劫持父类的 init)。我想要一个没有强制转换的“特殊”[[NSSuperString alloc] init]。在 init 中返回 NSString 时,我需要 (NSSuperString *)[[NSSuperString alloc] init] 以便静态分析器看到我有一个子类(当然当 NSSuperString 没有实现 init 时)。声明为本地 var 时,也会出现警告而不进行强制转换。
  • 如果你使用[NSSuperString alloc] init],有或没有NSSuperString,有initinstancetype意味着你得到一个NSSuperString。这是instancetype 的一部分。
【解决方案3】:

与此同时,Apple 添加了一种新方法来声明 init 方法的返回类型。

它是instancetype。阅读更多关于它的信息,例如here

【讨论】:

  • 据我了解,Clang 实际上在内部自动将 id 视为 init 方法的实例类型(但我认为它不适用于类便利方法)
【解决方案4】:

init 有可能实际返回不同类的实例,因此使用id。不能说我在实践中见过这种情况,但是嘿:)

【讨论】:

  • 你一直在实践中使用它:NSArray/NSMutableArray, NSString/NSMutableString
  • @JoshCaswell 那么为什么不让它返回一个 NSArray* 而不是 id 呢?多态性仍然有效。
  • @RamyAlZuhouri:语义问题:使用“NSArray *”类型的表达式初始化“NSMutableArray *__strong”的指针类型不兼容
  • 这只是鸭子打字。实际上类型是什么并不重要。重要的是它可以被视为您要求的类型。如果您要求构造 NSMutableArray,则可以将结果视为 NSMutableArray。即使不是。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-18
相关资源
最近更新 更多