Object
以“多态”方式与类型关联与id
as之间有区别NSObject *
吗?
以什么方式:
NSString* aString = @"Hello";
id anObj = aString;
不同于:
NSString* aString = @"Hello";
NSObject* anObj = aString;
Object
以“多态”方式与类型关联与id
as之间有区别NSObject *
吗?
以什么方式:
NSString* aString = @"Hello";
id anObj = aString;
不同于:
NSString* aString = @"Hello";
NSObject* anObj = aString;
id
是 Objective-C 中使用的一个特殊关键字,表示“某种对象”。它不包含isa
指针(isa
,使对象可以访问其类,并通过该类访问它所继承的所有类),因此您会丢失有关该对象的编译时信息。
NSString* aString = @"Hello";
id anObj = aString;
NSObject
包含isa
指针。
NSString* aString = @"Hello";
NSObject* anObj = aString;
考虑以下代码:
id someObject = @"Hello, World!";
[someObject removeAllObjects];
在这种情况下, someObject 将指向一个NSString
实例,但编译器对该实例一无所知,除了它是某种对象之外。该removeAllObjects
消息由一些 Cocoa 或 Cocoa Touch 对象(例如NSMutableArray
)定义,因此编译器不会抱怨,即使此代码会在运行时生成异常,因为 NSString 对象无法响应removeAllObjects
。
重写代码以使用静态类型:
NSString *someObject = @"Hello, World!";
[someObject removeAllObjects];
意味着编译器现在将生成一个错误,因为它没有在它知道removeAllObjects
的任何公共接口中声明。NSString
id
是通用的。通过使用id
,您告诉编译器您稍后将填写有关使用的详细信息。编译器假定您拥有的任何代码都是正确的,并且不会警告您任何事情。在运行时检查以验证您正在尝试做什么,如果您的代码错误,您将获得异常。
NSObject
是具体的。通过使用NSObject
,您可以准确地告诉编译器对象是什么。当您尝试在其上调用方法时,将根据所NSObject
理解的内容检查它们。如果你犯了错误,你会得到编译时错误。
综上所述,您可以在这两种情况下强制转换以获取另一个 Class 类型。
您关心的是您将来要如何处理该参考。一般来说,使用NSObject
没有任何好处。
使用 id 时,您可以向其发送任何已知消息,而使用 NSObject * 时,您只能向其发送由 NSObject 声明的消息(不是任何子类的方法),否则会产生警告。