当我们可以使用 NSObject 时为什么还要使用 id 呢?

发布于 2024-12-11 18:22:08 字数 168 浏览 0 评论 0原文

我知道当我们想要创建一个未知值对象时我们使用 id。然而,我很好奇为什么苹果要选择 id 来决定它在运行时的值,当每个对象都是 NSObject 的子类时。因此,我们可以使用 NSObject *delegate 来代替 id delegate 有谁知道为什么吗?谢谢。

I know that when we want to create an unknown value object we use id. However, I'm curious that why did Apple to choose id which decides it's value during runtime, when every object is a subclass of NSObject. So instead of id delegate we could have used NSObject *delegate Does anyone know why? Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

如日中天 2024-12-18 18:22:09

每个对象都是 NSObject 的子类

这是不正确的。您可以创建一个从无到有扩展的对象作为根类。

这也许就是引入 id 的原因。

every object is a subclass of NSObject

That's not correct. You could make an object that extends from nothing as a root class.

That's perhaps why id was introduced.

梦断已成空 2024-12-18 18:22:08

id 删除类型,相当于说“这个对象响应任何对翻译可见的选择器”。当然,有责任在擦除类型时(以及在对它们进行类型转换时)确保您的程序正确。

如果类型是NSObject,那么如果选择器没有在 NSObject 的接口或其采用的协议中声明,编译器会说“NSObject 可能不会响应选择器”。在这种情况下,您还可以添加类型转换以将其转换为您期望的类型。

对于严格/正确的类型,编译器可以介入并帮助您,这很棒,因为 ObjC 是一种非常动态的语言。

id 在使用(或构建)集合类型时特别有用。添加对象不会成为问题,除非您定义了新的根类型(不继承自 NSObject)。如果我们要将其用作基类 (NSObject) 之外的其他内容,则从集合中获取值需要进行类型转换。

Objective-C 不支持泛型 - 例如,您不能声明 NSStringNSArray。您可以使用 NSString 填充 NSArray 并通过 id 传递它,以便在不保留类型安全时获得更自然的编写风格(类似于泛型) )。

那么,让我们用一些实际的代码来扩展它。

示例 A

NSString * string = [array objectAtIndex:0]; // << trust me (via id)
return [string length];
-or-
return [[array objectAtIndex:0] length]; // << trust me (via id)

示例 B

现在假设 id 不可用,我们修复了所有编译器警告,因为这是正确的做法:

NSString * string  = (NSString*)[array objectAtIndex:0]; // << typecast == trust me
return [string length];
-or-
return [(NSString*)[array objectAtIndex:0] length]; // << typecast == trust me

id 不会在运行时决定其值,任何 NSObject 也不会。 ObjC 对象不执行隐式提升,它们只是在没有正式提升的情况下强制转换指针。

与您的示例相关,我实际上将我的委托和参数声明为带有协议的 NSObject:

NSObject<MONShapeDelegate>* delegate;

id erases the type and it is equivalent to saying "this object responds to any selector visible to the translation". Of course, it is your responsibility to make sure your program is correct when you erase types (and also when you typecast them).

If the type were NSObject, then the compiler would say "NSObject may not respond to selector" if the selector was not declared in NSObject's interface or the protocols it adopts. In that event, you could also add a typecast to cast it to the type you expect.

With strict/correct types, the compiler can kick in and help you out, which is great because ObjC is a very dynamic language.

id is particularly useful when using (or building) collections types. Adding an object would not be a problem unless you defined a new root type (does not inherit from NSObject). Getting a value from the collection would require a typecast if we were to use it as something other than our base class (NSObject).

Objective-C does not support generics - you cannot, for example, declare an NSArray of NSStrings. You can populate an NSArray with NSStrings and pass this through id for a more natural written style when type safety is not preserved (a la generics).

So, let's expand on this with some real code.

Example A

NSString * string = [array objectAtIndex:0]; // << trust me (via id)
return [string length];
-or-
return [[array objectAtIndex:0] length]; // << trust me (via id)

Example B

And now let's say id is not available and we fix all our compiler warnings because it's the right thing to do:

NSString * string  = (NSString*)[array objectAtIndex:0]; // << typecast == trust me
return [string length];
-or-
return [(NSString*)[array objectAtIndex:0] length]; // << typecast == trust me

id doesn't decide its value at runtime, nor does any NSObject. ObjC objects don't perform implicit promotions, they just cast the pointer through without formal promotion.

Related to your example, I actually declare my delegates and parameters as NSObjects with protocols:

NSObject<MONShapeDelegate>* delegate;
对不⑦ 2024-12-18 18:22:08

每个对象都是 NSObject 的子类

这是一个不正确的说法。您可以创建不继承自 NSObject 的对象。并不真正推荐,但这是可能的。

NSProxy 就是一个例子 - 它不是从 NSObject 继承的。

every object is a subclass of NSObject

That is an incorrect statement. You can create objects that do not inherit from NSObject. it's not really recommended, but it is possible.

NSProxy is an example - it does not inherit from NSObject.

余厌 2024-12-18 18:22:08
typedef struct objc_object {
    Class isa;
} *id;

以上是Objective-C语言中id的实际定义。 Objective-C 运行时系统是围绕 idClass 构建的。与 NSObject 或公共超类无关。

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocObjectsClasses.html#//apple_ref/doc/uid/TP30001163-CH11-SW3

NSObject 类

NSObject 是根类,因此没有超类。它定义了
Objective-C 对象和对象交互的基本框架。
它传递给继承自的类和类的实例
它表现得像对象并与运行时合作的能力
系统。

不需要从另一个类继承任何特殊行为的类
尽管如此,该类仍应成为 NSObject 类的子类。
类的实例至少必须具有如下行为的能力
运行时的 Objective-C 对象。

NSObject 类比重新发明更简单、更可靠
它在一个新的类定义中。

我认为,这是因为它最初是 C 而不是 C++ (或其他更严格的类型语言)。

typedef struct objc_object {
    Class isa;
} *id;

Above is the actual definition of the id in Objective-C language. Objective-C runtime system is built around id and Class. Nothing have to do with NSObject or common super class.

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocObjectsClasses.html#//apple_ref/doc/uid/TP30001163-CH11-SW3

The NSObject Class

NSObject is a root class, and so doesn’t have a superclass. It defines
the basic framework for Objective-C objects and object interactions.
It imparts to the classes and instances of classes that inherit from
it the ability to behave as objects and cooperate with the runtime
system.

A class that doesn’t need to inherit any special behavior from another
class should nevertheless be made a subclass of the NSObject class.
Instances of the class must at least have the ability to behave like
Objective-C objects at runtime.
Inheriting this ability from the
NSObject class is much simpler and much more reliable than reinventing
it in a new class definition.

I think, this is because it is originally C not C++ (or other more strict typing languages).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文