【问题标题】:What is the different between an id and NSObject in Objective C?Objective C 中的 id 和 NSObject 有什么区别?
【发布时间】:2010-05-23 10:48:57
【问题描述】:

这有什么不同:

身份证号:

#import <objc/Object.h>

@interface Forwarder : Object
{
    id something;
}

NSObject:

#import <objc/Object.h>

@interface Forwarder : Object
{
    NSObject *something;
}

你。

【问题讨论】:

标签: objective-c


【解决方案1】:

unixjunkie blog 中的This Greg MILLER's blog post 总结了差异

部分摘录:

Objective-C 中以下三个声明之间的区别经常令人困惑:

id foo1;
NSObject *foo2;
id<NSObject> foo3;
  • 第一个是最常见的。
    它只是声明了一个指向某个 Objective-C 对象的指针(参见/usr/include/objc/objc.h)。 id 不会向编译器提供有关对象实际类型的任何信息,因此编译器无法为您进行编译时类型检查。

  • 仅仅因为我们知道 id 是一个 Objective-C 对象并不意味着它指向一个派生自 NSObject 的对象,或者它甚至具有诸如保留和释放之类的常用方法。
    一种解决方案是使用 NSObject* 静态键入我们的变量,如上面的数字 2 所示。
    这为编译器提供了关于 foo2 指向的对象的类的信息,因此如果您向 foo2 发送 NSObject 没有响应的消息,编译器可以发出警告。这意味着您可以安全地调用 retain、release、description 等,但如果您调用 length 或 count 或 NSObject 没有响应的任何内容,编译器会发出警告。

  • 1234563 sup>** 名为NSObject 的协议(@protocol)。还有一个名为NSObject 的类确实符合NSObject 协议,但它们是两个不同的东西
    编译器将确保您分配给该指针的所有对象都符合所需的协议。
    像这样键入的指针可以安全地保存任何NSObject(因为NSObject 符合NSObject 协议),但它也可以保存任何NSProxy,因为NSProxy 也符合NSObject 协议。
    英文声明id&lt;NSObject&gt;foo3;说“foo3 是指向任何类型的对象的指针,其行为类似于 NSObject”。
    这是非常强大、方便和富有表现力的。实际上,我们通常不关心对象是什么类型,我们只关心它响应我们想要发送它的消息(例如,保留、释放)。

如果您不想(或不能)进行任何类型检查,请使用普通 id。对于不知道它们返回的对象类型的方法的返回类型(例如,+alloc),这很常见。将委托声明为类型 id 也很常见,因为委托通常在运行时使用 respondsToSelector: 检查,并且通常不保留。

但是,如果您确实需要编译时类型检查,则必须在第二种和第三种情况之间做出选择。好吧,让我帮你吧——你想要第三个案子! :-) 我非常、非常、非常罕见地看到 NSObject * 工作但 id 不能工作的情况。并且使用协议形式的优点是它可以与 NSProxys 一起使用。

【讨论】:

  • 在我看来,respondsToSelector 选择器不适用于第三种情况。那么我会推荐第二种情况。
【解决方案2】:

实际的区别是您不需要将id 进行类型转换,但您通常需要在使用之前将NSObject * 类型转换为某个东西。 NSObject 是几乎所有其他类都派生自其中的基类,id 更像是一个语言关键字。

【讨论】:

    【解决方案3】:

    id 响应任何方法而没有编译器警告; NSObjects 只响应 NSObject 中定义的方法而不发出警告,包括 NSObject 协议。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-02
      • 1970-01-01
      • 1970-01-01
      • 2012-05-03
      • 2010-10-01
      • 2012-09-12
      • 2010-10-06
      • 2010-11-21
      相关资源
      最近更新 更多