03-isa指针 & superclass指针

简介: 03-isa指针 & superclass指针

实例(instance)对象

实例对象是通过alloc出来的对象,每次alloc都会产生一个新的实例对象;实例对象的存储信息:

  • isa指针
  • 其他的成员变量
  • ...
NSObject *obj1 = [[NSObject alloc] init];
NSObject *obj2 = [[NSObject alloc] init];

obj1和obj2是NSObject的实例对象,是两个不同的对象,占据着两块不同的内存空间;

类(class)对象

每个类在内存中有且只有一个class对象;类对象的存储信息:

  • isa指针
  • superclass指针
  • 类的属性信息(@property)
  • 类的对象方法信息(instancemethod)
  • 类的协议信息(protocol)
  • 类的成员变量信息(ivar)
  • ...

Class objCls1 = [obj1 class];
Class objCls2 = [obj2 class];
Class objCls3 = [NSObject class];
Class objCls4 = object_getClass(obj1);
Class objCls5 = object_getClass(obj2);
Class objCls6 = objc_getClass("NSObject");
NSLog(@"实例对象 - %p - %p",
      obj1, obj2);
NSLog(@"类对象 - %p - %p - %p - %p - %p - %p",
      objCls1, objCls2, objCls3, objCls4, objCls5, objCls6);

运行结果

实例对象 - 0x100682040 - 0x100680720
类对象 - 0x7fff8897a008 - 0x7fff8897a008 - 0x7fff8897a008 - 0x7fff8897a008 - 0x7fff8897a008 - 0x7fff8897a008

objCls1 - objCls6都是NSObject的类对象,它们是同一个对象;

元类(meta-class)对象

每个类在内存中有且只有一个meta-class对象;元类对象的存储信息:

  • isa指针
  • superclass指针
  • 类的类方法信息
  • ...

Class metaCls1 = object_getClass(objCls1);
Class metaCls2 = object_getClass(objCls2);
Class metaCls3 = objc_getMetaClass("NSObject");
NSLog(@"元类对象 - %p - %p - %p", metaCls1, metaCls2, metaCls3);
NSLog(@"%d", class_isMetaClass(metaCls1));

运行结果

元类对象 - 0x7fff88979fe0 - 0x7fff88979fe0 - 0x7fff88979fe0
1

isa指针

通过之前OC的底层实现,我们知道了NSObject的底层编译是NSObject_IMPL结构体,结构体内部是一个Class类型的isa,而Class类型为objc_class结构体指针,故isa也是一个指针;

@interface Person : NSObject
- (void)instanceMethod;
+ (void)classMethod;
@end

实例对象的isa指向类对象(class)

当我们调用Person中instanceMethod方法时,通过实例对象的isa找到class,最后找到instanceMethod方法进行调用;

类对象的isa指向元类对象(meta-class)

当我们调用Person中classMethod时,通过class的isa找到元类对象,最后找到classMethod方法进行调用;

类对象的superclass指针

@interface Person : NSObject
- (void)instanceMethod;
@end
@interface Student : Person
@end

当我们调用Student的instanceMethod方法时,先通过Student的isa找到class对象,然后通过superclass找到Person的class,最后找到instanceMethod实例方法进行调用;元类对象的superclass指针

@interface Person : NSObject
+ (void)classMethod;
@end
@interface Student : Person
@end

当我们调用Student的classMethod方法时,先通过Student的isa找到meta-class对象,然后通过superclass找到Person的meta-class,最后找到classMethod类方法进行调用;

isa指针 & supercalss指针

通过下方这张图,我们来分析一下整个查找流程

虚线代表isa指针,实现代表superclass指针;

  • instance的isa指向class;
  • class的isa指向meta-class;
  • meta-class的isa指向基类的meta-class;
  • class的superclass指向父类的class,如果没有父类,superclass指针为nil
  • meta-class的superclass指向父类的meta-class;
  • 基类的meta-class的superclass指向基类的class
  • instance调用对象方法的轨迹:通过isa找到class,方法不存在,就通过superclass找父类class;
  • 调用类方法的轨迹:通过isa找meta-class,方法不存在,就通过superclass找父类;

调用方法的时候,如果寻找上层依旧找不到,会报一个很经典的错误unrecognized selector sent to instance

此处还有一个注意点,注意看图中warn那条线,当基类的meta-class对象查找类方法如果不存在的话,会向基类的类对象里面去找,具体意思是什么?可以参考下方的示例:

@interface Person : NSObject
+ (void)test;
@end
@implementation Person
@end
@interface NSObject (Extention)
@end
@implementation NSObject (Extention)
- (void)test {
    NSLog(@"NSObject - (void)test");
}
@end

调用test方法

[Person test];

运行结果

NSObject - (void)test

当我们调用test类方法的时候,发现在元类对象meta-class以及元类基类对象meta-class中都无法查找到,这个时候就会去类的基类对象class里面去找,执行到了类基类对象class里面的实例方法,故调用了NSObject里面的test实例方法;

相关文章
|
11月前
|
存储 C++
04-深入了解isa指针以及内部结构
04-深入了解isa指针以及内部结构
52 0
04-深入了解isa指针以及内部结构
|
存储 编译器 iOS开发
iOS - isa、superclass指针,元类superclass指向基类本身(下)
本文已同步至掘金:iOS - isa、superclass指针,元类superclass指向基类本身
iOS - isa、superclass指针,元类superclass指向基类本身(下)
|
iOS开发
iOS - isa、superclass指针,元类superclass指向基类本身(上)
本文已同步至掘金:iOS - isa、superclass指针,元类superclass指向基类本身
iOS - isa、superclass指针,元类superclass指向基类本身(上)
|
2月前
|
C语言
指针进阶(C语言终)
指针进阶(C语言终)
|
5天前
|
C语言
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)
|
5天前
|
C语言
【C初阶——指针4】鹏哥C语言系列文章,基本语法知识全面讲解——指针(4)
【C初阶——指针4】鹏哥C语言系列文章,基本语法知识全面讲解——指针(4)
|
5天前
|
存储 编译器 C语言
【C初阶——指针3】鹏哥C语言系列文章,基本语法知识全面讲解——指针(3)
【C初阶——指针3】鹏哥C语言系列文章,基本语法知识全面讲解——指针(3)
|
1月前
|
编译器 C语言
【C语言初阶】指针篇—下
【C语言初阶】指针篇—下
|
1月前
|
存储 C语言
【C语言初阶】指针篇—上
【C语言初阶】指针篇—上