类类型
类实际上是对一类对象的描述。类实质上定义了一种数据类型。这种类型不仅仅是基于类中的数据结构(实例变量),而且还是基于其中定义的行为(方法)。
类名是可以出现在C中允许的任何限定符的位置的。例如,可以作为sizeof()的参数:
int i = sizeof(Rectangle);
静态类型
程序中可以使用确切的类名来代替id类型:Rectangle *myRectangle;
由于这种声明对象的方式可以告诉编译器该对象的类型信息,因此这种方式被称为是静态类型。id实际上是一个指针,而对象的静态类型就是指向该对象的指针的类型。这种静态类型的方式显示地给出了对象的类型;而id则隐藏了对象的这种类型。
这种静态类型使得编译器能够在编译的时候进行类型检查。例如,当检查到对象不能响应接收的消息的时候会给出编译告警;或者是对id类型的某些应用限制放松了。另外,也可以使程序的阅读者明确程序编写者的意图。然而,这种方式并不影响动态绑定机制或者是改变在运行时才对对象的类型进行判定的事实。
我们可以把对象的类型静态地转化为对应的类,或者是该类的任意一个超类。例如,继承关系使得一个Rectangle对象本身也是一个Graphic类的对象(参见前面的图1-1),因此,一个Rectangle类的实例是可以被静态地转换成Graphic类型的:
Graphic *myRectangle;
这种静态地类型转换是可行的,因为一个Rectangle类的对象本身就是一个Graphic类的对象。更确切地说,尽管Rectangle类的对象含有Shape类以及Rectangle类的实例变量以及方法,但这改变不了他是一个Graphic类的对象的事实。在编译的时候,由于上面的这种写法,编译器会把myRectangle对象看作是Graphic类型来进行类型检查的。然而在运行时,如果myRectangle对象生成了,并作为Rectangle类的实例进行了初始化,那么他是会被当作Rectangle类的对象来对待的,而不是Graphic类的对象。
关于这种静态类型的的更多信息以及它所带来的好处请参阅"使能静态类型"这一章节。
类型“自省”
对象可以在运行的时候对自身的真实类型进行判断。从NSObject类中继承而来的方法isMemberOfClass:就是用来判断对象是否为某个特定的类的对象:if([对象 isMemberOfClass:类名])
...
同时在NSObject类中还定义了方法isKindOfClass:方法。该方法用于检测消息接收者是否是某个类的派生类的对象或者是某个类的对象(或者说某个类是否在该对象所属类的继承关系图中):
if ([对象 isKindOfclass:类名])
...
其中那些可以使得isKindOfClass:方法返回YES的类的集合就是该对象可以被静态地进行类型转换的类型的集合。
类型的“自省”并不局限于只是类型信息。本章的后续小节中会讨论返回值为类对象的方法,这样可以检测某个对象是否可以响应指定的消息,以及获取对象的其他相关信息。
更多关于isMemberOfClass:信息请参阅“NSObject 类参考及其相关方法。