第14条:理解“类对象”的用意
1. 类型信息查询
在运行期检视对象类型的操作叫做“类型信息查询”(introspection,内省)。
*** Objective-C基础知识 ***
NSString *pointerVaribel = @"Some string";
解释:pointerVaribel变量指向NSString实例,该变量也叫指针。
typedef struct objc_object *id;
struct objc_object { Class isa; };
// 等价于
typedef sturct objc_object {
Class isa;
} *id;
解释:该结构体描述了Objective-C对象所用的数据结构。其中,isa指针定义了对象所属的类。
typedef struct objc_class *Class;
struct objc_class {
Class isa;
Class super_class;
const char *name;
long version;
long info;
long instance_size;
struct objc_ivar_list *ivars;
#if defined(Release3CompatibilityBuild)
struct objc_method_list *methods;
#else
struct objc_method_list **methodLists;
#endif
struct objc_cache *cache;
struct objc_protocol_list *protocols;
};
解释:该结构体存放类的“元数据”。其中,isa指针定义了另外一个类——元类(metaclass),用来表述类对象本身所具备的元数据。super_class定义了本类的超类。
*** 类方法 *** :类方法可以理解成类对象的实例方法,每个类仅有一个“类对象”,而每个“类对象”仅有一个与之相关的“元类”。
类继承体系 图例
总结:通过这张布局关系图即可执行“类型信息查询”。开发者可以查出对象是否能响应某个选择器,是否遵从某项协议,并且能看出此对象位于“类继承体系”(class hierarchy)的哪一部分。
2. 在类继承体系中查询类型信息
*** 2.1 类型信息查询方法 ***
可以用类型信息查询方法来检视类继承体系。
“isMemberOfClass:”能够判断出对象是否为某个特定类的实例,而“isKindOfClass:”则能够判断出对象是否为某类或其派生类的实例。
*** 2.2 等同性判断方法 ***
使用“==”操作符来比较类对象是否等同。原因在于,类对象是“单例”(singleton),在应用程序范围内,每个类的Class仅有一个实例,也就是说,借助“==”操作符可以精确判断出对象是否为某类实例。如:
id object = /* ... */;
if ([object class] == [EOCSomeClass class]){
// 'object' is an instance of EOCSomeClass
}
总结:应该尽量使用类型信息查询方法,而不应该直接比较两个类对象是否等同。
要点
- 每个实例都有一个指向Class对象的指针,用以表明其类型,而这些Class对象则构成了类的继承体系。
- 如果对象类型无法在编译期确定,那么就应该使用类型信息查询方法(内省)来探知。
- 尽量使用类型信息查询方法来确定对象类型,而不要直接比较类对象,因为某些对象可能实现了消息转发功能。
网友评论