类的获取
在日常开发当中我们一般通过如下方式获取对象所属的类;
Class class1 = [FMUserInfo alloc].class;
除此之外还有如下等方式来获取某个类:
Class class2 = [FMUserInfo alloc].class;
Class class3 = object_getClass([FMUserInfo alloc]);
通过运行可以看到,不管通过什么方式获取,其内存地址始终为一个
类的结构
我们知道类Class的类型是objc_class类型
typedef struct objc_class *Class;
通过查看源码(我这里是838.1版本)可以查看其定义部分:
//类对象
struct objc_class : objc_object {
// Class ISA; // 8
Class superclass;// 8
cache_t cache; // 16 // formerly cache pointer and vtable
class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags //
......
}
类其实是一个继承自的objc_object结构体,而我们知道对象的本质其实也是objc_object,因此类其实也是一个对象,即类对象。观objc_class定义,其内部包含isa、superclass、cache、bits等结构。
isa类的isa指针superclass继承的类cache缓存bits类的内部数据
类的isa
我们知道对象的isa指向的是类,而前文中也说,类其实也是一个对象,那么类对象的isa指向的又是谁呢?
我们先通过实例对象p的
isa获取到了类对象FMUserInfo,那么我们用同样的方式查看下类的isa指向的是谁。
通过实际测试发现,类的isa同样指向的是FMUserInfo,但是这两个FMUserInfo的地址明显不是同一个,我们通过p/x [FMUserInfo class]打印下FMUserInfo类对象的地址。显然类的地址为前者,后者即为类的元类。
元类的isa
我们继续打印下元类的isa指向的是谁呢?
通过打印发现元类的isa指向的是NSObject,那么此处的NSObject是否系统定义的NSObject为同一个呢?
明显这两者也不是同一个,这里打印出来的
NSObject为根元类,我们再次用相同的方式打印,可以发现根元类的isa指向本身。
所以其
isa的指向图如下图所示:
类与元类
上文中我们探讨了对象、类与元类的isa的指向关系,那么类与元类之间的继承关系又是如何?
类的继承链
我们准备一个子类FMManagerInfo,其继承自FMUserInfo,通过runtime提供的class_getSuperclass方法来获取该类继承自哪个类,
FMManagerInfo *t = [FMManagerInfo alloc];
FMUserInfo *p = [FMUserInfo alloc];
NSLog(@"%@-%@",t,p);
NSLog(@"%@",class_getSuperclass(FMManagerInfo.class));
NSLog(@"%@",class_getSuperclass(FMUserInfo.class));
NSLog(@"%@",class_getSuperclass(NSObject.class));
其运行结果如下:
其继承关系如下:
graph LR
A[子类] --继承自--> B[父类] --继承自--> C[NSObject] --继承自--> D[null]
元类链
那么元类的继承关系呢?objc_getMetaClass方法可以用来获取某个类的元类,所以与class_getSuperclass相结合,我们用如下代码来测试下:
NSLog(@"%@--元类为:%@ 地址为%p,其父类为%@,元类的父类为%@ 地址为:%p",FMManagerInfo.class,objc_getMetaClass([NSStringFromClass(FMManagerInfo.class) cStringUsingEncoding:NSASCIIStringEncoding]),objc_getMetaClass([NSStringFromClass(FMManagerInfo.class) cStringUsingEncoding:NSASCIIStringEncoding]),class_getSuperclass(FMManagerInfo.class),class_getSuperclass(objc_getMetaClass([NSStringFromClass(FMManagerInfo.class) cStringUsingEncoding:NSASCIIStringEncoding])),class_getSuperclass(objc_getMetaClass([NSStringFromClass(FMManagerInfo.class) cStringUsingEncoding:NSASCIIStringEncoding])));
NSLog(@"%@--元类为:%@ 地址为%p,其父类为%@,元类的父类为%@ 地址为:%p",FMUserInfo.class,objc_getMetaClass([NSStringFromClass(FMUserInfo.class) cStringUsingEncoding:NSASCIIStringEncoding]),objc_getMetaClass([NSStringFromClass(FMUserInfo.class) cStringUsingEncoding:NSASCIIStringEncoding]),class_getSuperclass(FMUserInfo.class),class_getSuperclass(objc_getMetaClass([NSStringFromClass(FMUserInfo.class) cStringUsingEncoding:NSASCIIStringEncoding])),class_getSuperclass(objc_getMetaClass([NSStringFromClass(FMUserInfo.class) cStringUsingEncoding:NSASCIIStringEncoding])));
NSLog(@"%@--元类为:%@ 地址为%p,其父类为%@,元类的父类为%@ 地址为:%p",NSObject.class,objc_getMetaClass([NSStringFromClass(NSObject.class) cStringUsingEncoding:NSASCIIStringEncoding]),objc_getMetaClass([NSStringFromClass(NSObject.class) cStringUsingEncoding:NSASCIIStringEncoding]),class_getSuperclass(NSObject.class),class_getSuperclass(objc_getMetaClass([NSStringFromClass(NSObject.class) cStringUsingEncoding:NSASCIIStringEncoding])),class_getSuperclass(objc_getMetaClass([NSStringFromClass(NSObject.class) cStringUsingEncoding:NSASCIIStringEncoding])));
所以其整个流程图如下
元类与父类
那么对于某个自定义类如FMUserInfo,父类与元类的关系如何?
// FMUserInfo -- 元类的父类就是父类的元类
Class FMetaClass = class_getSuperclass(objc_getMetaClass([NSStringFromClass(FMUserInfo.class) cStringUsingEncoding:NSASCIIStringEncoding]));
Class FsuperClass = objc_getMetaClass([NSStringFromClass(class_getSuperclass(FMUserInfo.class)) cStringUsingEncoding:NSASCIIStringEncoding]);
NSLog(@"元类的父类%@ - %p",FMetaClass,FMetaClass);
NSLog(@"父类的元类%@ - %p",FsuperClass,FsuperClass);
通过打印发现元类的父类与父类的元类其实是同一个,所以也就得出了经典的继承关系链;