“多态”方式Object
与类型id
的关联与NSObject *
的关联是否存在差异?
以什么方式:
NSString* aString = @"Hello";
id anObj = aString;
不同于:
NSString* aString = @"Hello";
NSObject* anObj = aString;
答案 0 :(得分:10)
id
是Objective-C中用来表示“某种对象”的特殊关键字。它不包含isa
指针(isa
,使对象可以访问其类并且,通过该类,它继承的所有类),所以你丢失了有关该对象的编译时信息。
NSString* aString = @"Hello";
id anObj = aString;
NSObject
包含isa
指针。
NSString* aString = @"Hello";
NSObject* anObj = aString;
来自Objective-C Is a Dynamic Language
请考虑以下代码:
id someObject = @"Hello, World!";
[someObject removeAllObjects];
在这种情况下,someObject将指向NSString
实例,但除了它是某种对象之外,编译器对该实例一无所知。 removeAllObjects
消息由一些Cocoa或Cocoa Touch对象(例如NSMutableArray
)定义,因此编译器不会抱怨,即使此代码会在运行时生成异常,因为NSString对象不能回复removeAllObjects
。
重写代码以使用静态类型:
NSString *someObject = @"Hello, World!";
[someObject removeAllObjects];
表示编译器现在会生成错误,因为removeAllObjects
未在它知道的任何公共NSString
接口中声明。
答案 1 :(得分:6)
id
是通用的。通过使用id
,您告诉编译器您将在以后填写有关使用的详细信息。编译器假定您拥有的任何代码都是正确的,并且不会向您发出任何警告。在运行时,会进行检查以验证您要执行的操作,如果您的代码错误,您将收到异常。
NSObject
具体。通过使用NSObject
,您可以准确地告诉编译器对象是什么。当您尝试在其上调用方法时,将根据NSObject
理解的内容进行检查。如果你犯了错误,你会得到编译时错误。
所有这一切,你可以在两种情况下进行转换以获得另一种类型。
您的关注点是您将来要参考的内容。通常,使用NSObject
没有任何好处。
答案 2 :(得分:1)
答案 3 :(得分:0)
使用id时,可以发送任何已知消息,使用NSObject *时,只能发送NSObject声明的消息(不是任何子类的方法),否则会产生警告。