高效编写代码的方法(十二):类的内省

前言

在之前几篇文章中,我们了解到了一个类的方法是怎么在类中进行存储的;当一个类的实现方法无法找到时,消息转发机制又是如何起作用的。所以,接下来我们要去了解 类 的本身,也就是消息的接收者(receiver)。
在运行时候,我们的程序是怎么知道该像哪一个类去寻找消息的实现呢?

内省

一般来说,如果我们像指定类的实例对象发送消息之后,编译器会检查该类是否有该消息方法的接口,如果没有则会抛出报错或警告。但是对于id这种特殊的类(id可以代表任何一个NSObject),所以编译器会假设id可以对任何消息做出反应而不抛出报错或警告,但在实际运行时可能崩溃。
同时因为objc中类的方法是可以动态进行添加的,所以编译器的检查对于objc来说已经不足够了。

runtime提供了一种类的内省机制,这其中包括了isKindOfClass等我们经常会使用到的方法,这些方法都是NSObject的protocol一部分,所以所有的对象都具有这一套内省方法。

结构

在runtime中,对象以结构构体保存,id类的对象的结构体如下:

typedef struct objc_object {  
    Class isa;  
} *id; 

由此可见,其中包含一个Class类的变量isa,isa指向该对象的类。
所以NSString *str , str中的isa就指向NSString。

Class对象在runtime中也有结构体定义:

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;  
    struct objc_method_list **methodLists;  
    struct objc_cache *cache;  
    struct objc_protocol_list *protocols;  
}; 

此结构体的首个变量是isa指针,这说明Class本身也是一个Objective-C对象。结构体里还有个变量叫做super_class,它指向了该类的父类。类对象所属的类型(也就是isa指针所指向的类型)是另外一个类,叫做“元类”(metaclass)。
metaClass是用来描述这个类的数据的一个对象。


类的关系图

isKindOfClass和isMemberOfClass的具体使用就不多说了,两个方法都是通过结构体内的isa指针和super_class指针来确定该类的继承关系。
猜想一下isMemberOfClass可能就是通过isa来判断,而isKindOfClass就主要是通过super_class来实现查找判断。

总结

  • 1 每个对象都有一个指向Class对象的指针,用来表明类型,而这些Class对象则构成了类的继承体系。
  • 2 如果对象类型无法在编译期确定,那么就应该使用内省方法来探知。
  • 3 尽量使用类型信息查询方法来确定对象类型,而不要直接比较类对象,因为某些对象可能实现了消息转发功能。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,775评论 0 9
  • 第一章 熟悉Objective-C 1. 了解Objective-C语言的起源Objective-C(以下简称OC...
    还是不够辣阅读 918评论 0 5
  • 这篇文章完全是基于南峰子老师博客的转载 这篇文章完全是基于南峰子老师博客的转载 这篇文章完全是基于南峰子老师博客的...
    西木阅读 30,636评论 33 466
  • 参考链接: http://www.cnblogs.com/ioshe/p/5489086.html 简介 Runt...
    乐乐的简书阅读 2,156评论 0 9
  • 看到这个主题,突然想到一个亲密的朋友。 为什么想到他呢,先看看发生在他身上的事吧。 之前他说不知道该从事什么行业,...
    王续晓阅读 161评论 0 0