OC对象模型细节
主要介绍Objective-C对象模型的实现细节,以及Objective-C语言对象模 型中对isa swizzling(isa-swizzling就是类型混合指针机制)和method swizzling(在没有一 个类的实现源码的情况下,想改变其中一个方法的实现)的支持。希望本文能加深大家 对Objective-C对象的理解。
ISA指针
Objective-C是一门面向对象的编程语言。
每一个 对象 都是一个类的实例。
每一个对象 都有一个名为isa的指针,指向该对象的类。
每一个 类 述了一系列它的实例的特点,包括成员变量的列表,成员函 数的列表等。
每一个对象 都可以接受消息,而对象能够接收的消息列表是保存在它所 对应的类中。
在XCode中按Shift + Command + O, 然后输入NSObject.h和objc.h,可以打开 NSObject的定义头文件,通过头文件我们可以看到,NSObject就是一个包 含isa指针的结构体,如下图所示:
按照面向对象语言的设计原则,所有事物都应该是对象(严格来说Objective-C并没有完全做到这一点,因为它有象int, double这样的简单 变量类型)。
在Objective-C语言中,每一个类实际上也是一个对象。每一个类也有一个名为isa的指针。每一个类也可以接受消息,例如[NSObject alloc],就是 向NSObject这个类发送名为alloc消息。
在XCode中按Shift + Command + O, 然后输入runtime.h,可以打开Class的定 义头文件,通过头文件我们可以看到,Class也是一个包含isa指针的结构 体,如下图所示。(图中除了isa外还有其它成员变量,但那是为了兼容 非2.0版的Objective-C的遗留逻辑,大家可以忽略它。)
因为类也是一个对象,那它也必须是另一个类的实列,这个类就是元类(metaclass)。
元类保存了类方法的列表。当一个类方法被调用时,元类会首先查找它本 身是否有该类方法的实现,如果没有,则该元类会向它的父类查找该方 法,直到一直找到继承链的头。
元类(metaclass)也是一个对象,那么元类的isa指针又指向哪里呢?为了设 计上的完整,所有的元类的isa指针都会指向一个根元类
(root metaclass)。
根元类(root metaclass)本身的isa指针指向自己,这样就行成了一个闭 环。上面到,一个对象能够接收的消息列表是保存在它所对应的类中 的。在实际编程中,我们几乎不会遇到向元类发消息的情况,那它的isa 指针在实际上很少用到。不过这么设计保证了面向对象的干净,即所有事 物都是对象,都有isa指针。
我们再来看看继承关系,由于类方法的定义是保存在元类(metaclass)中,而方法调用的规则是,如果该类没有一个方法的实现,则向它的父类继续查找。所以,为了保证父类的类方法可以在子类中可以被调用,所以子类的元类会继承父类的元类,换而言之,类对象和元类对象有着同样的继承关系。 我很想把关系说清楚一些,但是这块儿确实有点绕,下面这张图或许能够 让大家对isa和继承的关系清楚一些
该图中,最让人困惑的莫过于Root Class了。在实现中,Root Class是指
NSObject,我们可以从图中看出:
1.NSObject类包括它的对象实例方法。
2.NSObject的元类包括它的类方法,例如alloc方法。
3.NSObject的元类继承自NSObject类。
4.一个NSObject的类中的方法同时也会被NSObject的子类在查找方法时找到。
类的成员变量
如果把类的实例看成一个C语言的结构体(struct),上面说的isa指针就 是这个结构体的第一个成员变量,而类的其它成员变量依次排列在结构体 中。排列顺序如下图所示(图片来自《iOS 6 Programming Pushing the Limits》):