iOS>“ID”与NSObject

与“typesid相比,“多态”方式中的ObjectNSObject *有什么区别?

以什么方式:

 NSString* aString = @"Hello"; id anObj = aString; 

不同于:

 NSString* aString = @"Hello"; NSObject* anObj = aString; 

id是Objective-C中用来表示“某种对象”的一个特殊关键字。它不包含isa指针( isa ,它允许对象访问它的类,并且通过这个类来访问它所inheritance的所有类),所以你会丢失有关对象的编译时信息。

 NSString* aString = @"Hello"; id anObj = aString; 

在这里输入图像说明

NSObject包含isa指针。

 NSString* aString = @"Hello"; NSObject* anObj = aString; 

在这里输入图像说明

从Objective-C是一个dynamic语言

考虑下面的代码:

 id someObject = @"Hello, World!"; [someObject removeAllObjects]; 

在这种情况下,someObject将指向一个NSString实例,但是编译器对这个实例一无所知,除了它是某种对象。 removeAllObjects消息是由一些Cocoa或Cocoa Touch对象(如NSMutableArray )定义的,所以编译器不会抱怨,即使这个代码会在运行时产生一个exception,因为NSString对象不能响应removeAllObjects

重写代码以使用静态types:

 NSString *someObject = @"Hello, World!"; [someObject removeAllObjects]; 

意味着编译器现在会产生一个错误,因为removeAllObjects没有在它知道的任何公共NSString接口中声明。

id是通用的。 通过使用id你告诉编译器,你将在稍后填写使用的细节。 编译器假定你所拥有的任何代码都是正确的,并不会提醒你任何事情。 在运行时进行检查以validation你正在尝试做什么,如果你的代码是错误的,你会得到一个exception。

NSObject是特定的。 通过使用NSObject你正在告诉编译器到底是什么对象。 当你尝试调用它的方法时,它们将被检查NSObject理解的内容。 如果你犯了一个错误,你会得到编译时错误。

所有这一切说,你可以在两种情况下投入到另一个类的types。

你关心的是你将来要做什么。 一般来说,使用NSObject没有任何好处。

  1. id是一个语言关键字,但NSObject是目标c中的基类。
  2. 对于id,你不需要对对象进行types转换。 但是对于NSObject,你必须把它转换成NSObject。
  3. 一个id对象可以用来调用任何方法。 但NSObject对象可以用来调用NSObject中定义的特定方法

使用id时,可以发送任何已知的消息,当使用NSObject *时,只能发送NSObject声明的消息(不是任何子类的方法),否则会产生警告。