Object-C的继承isa指针

2016-03-23

isa指针

isa指针的作用就是追溯谁是谁的谁的关系,假设有一个人叫小明,小明是谁的儿子,是谁的孙子。isa指针就是建立一种继承关系。那么isa指针指向该实例对象的类对象。针对于一个对象本身来说,它并不知道如何去应答一个方法,它本身既不包含方法的实现,也不包含有方法的指针。而是间接的通过继承来的isa转到自己的类,才能知道某一个方法。
Object-C中,任何类的定义都是对象,类与类的对象(实例)并没有本质的区别,也就是类也是一种对象,叫类对象,通过类实例化后的对象,也称为对象,就就是Object-C面向对象语言的精髓,所以,任何对象都有isa指针。
每一个OC对象都有一个隐藏的数据结构,在这个数据结构中的第一个成员变量,它就是isa指针。
objc.h中能看到类定义:

1
2
3
4
5
6
7
8
9
10

#if !OBJC_TYPES_DEFINED
typedef struct objc_class *Class;
struct objc_object {
Class isa OBJC_ISA_AVAILABILITY;
};
typedef struct objc_object *id;
#endif
typedef struct objc_selector *SEL;

可以看出: Class是一个objc_class结构类型的指针,id 是一个objc_object结构体类型的指针。

NSObject.h里面:

1
2
3
4
5
6
7

@interface NSObject <NSObject> {

Class isa OBJC_ISA_AVAILABILITY;

}

再点开 Class 的定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

struct objc_class {

Class isa OBJC_ISA_AVAILABILITY;

#if !__OBJC2__

Class super_class OBJC2_UNAVAILABLE;

const char *name OBJC2_UNAVAILABLE;

long version OBJC2_UNAVAILABLE;

long info OBJC2_UNAVAILABLE;

long instance_size OBJC2_UNAVAILABLE;

struct objc_ivar_list *ivars OBJC2_UNAVAILABLE;

struct objc_method_list **methodLists OBJC2_UNAVAILABLE;

struct objc_cache *cache OBJC2_UNAVAILABLE;

struct objc_protocol_list *protocols OBJC2_UNAVAILABLE;

#endif

}

isa:是一个Class类型的指针,每个实例对象都有一个isa指针,并且指向对象的类,而Class里也有个isa的指针,指向元类,什么是元类?就是类方法的类,保存了类方法的列表。当某一个类方法被调用时,先会查找本身类方法中的实现方法,如果没有,元类会向他父类查找该方法。元类也是对象,最终指向根元类,根元类isa指向本身。
super_class:父类,如果该类已经是最顶层的根类,那么它为NULL

类通过类的isa指针指向元类,根元类isa指针指向本身。

举例:
假设新建一个Parent,继承与NSObject,里面有成员方法.

1
2
3
-(void)run;
+(void)sing;


在新建一个类Child,继承于Parent,里面有成员方法.

1
2
3
4
5

-(void)playC;
+(void)dump;


实例化一个对象Child *xiaoming = [[Child alloc]init];
注意:当我们调用[xiaoming class]的时候,xiaoming会通过它的isa指针去寻找xiaomingclass,即 Child
当我们调用[xiaoming superclass]的时候,xiaoming通过isa找到xiaomingclassChild类,在通过super_class,找到Parent类。

调用[xiaoming playC]xiaoming通过isa找到Child类,在class的方法列表里面找到playC

再试着调用[xiaoming run]xiaoming通过isa找到Child类,发现该类里面并没有这个方法,通过该类里面的super_class找到Parent类,在里面的方法列表找到了run

再是类方法[Child dump]Child通过isa找到Child类,通过该类的isa找到Childmetaclass,在metaclass的方法列表里面找到了+(void)dump

再试着调用[Child sing]Child通过isa找到Child类,通过该类的isa找到Childmetaclass,发现metaclass里面并没有这个方法,通过metaclass里面的super_class找到Parentmetaclass,在里面的方法列表找到了+(void)sing

objc_class有两种类型:
classmetaclass
class:实例对象的isa指向的结构体;
metaclassclassisa指向的一个结构体;

**`isa` 指针的最大作用 即是 寻找 `谁是谁的谁` 关系。**

总结

微信公众号:嘀咕嘀咕(iOSSharers)

扫二维码关注