对象,类,元类之间的关系

在之前的文章对象内存探索中,我们已经知道对象默认都有一个isa指针,这个指针指向的正式对象的类,而在oc中一切皆为对象,那类是否也有isa指针,他的指针指向的是谁呢?
带着这个疑问我们来看看
首先我们来看一个示例:

@interface HFPerson : NSObject
@end
HFPerson *p = [HFPerson alloc];
NSLog(@"%@---%p", p, p);

通过lldb我们来打印p的isa指针指向的类
(lldb) x/4gx p
0x28189a520: 0x000001a102e2d675 0x0000000000000000
0x28189a530: 0x0000000000000000 0x0000000000000000
0x000001a102e2d675 p的isa指针
(lldb) po 0x000001a102e2d675 & 0x0000000ffffffff8ULL
HFPerson
(lldb) p/x 0x000001a102e2d675 & 0x0000000ffffffff8ULL
(unsigned long long) $11 = 0x0000000102e2d670

这边就可以清楚看到isa指针指向的是HFPerson,也就是说对象的isa指向的是类
接下来我们看看类的isa指针
(lldb) x/4gx 0x0000000102e2d670
0x102e2d670: 0x0000000102e2d648 0x00000001f65e60d8
0x102e2d680: 0x00070002838e4a00 0x0005803900000000
(lldb) po 0x0000000102e2d648 & 0x0000000ffffffff8ULL
HFPerson
(lldb) p/x 0x0000000102e2d648 & 0x0000000ffffffff8ULL
(unsigned long long) $13 = 0x0000000102e2d648
咦也是HFPerson,但是我们看到$13 跟 前面的$11不一样,也就是说有两个HFPerson类?

接下来在继续往下看看会不会有第三个HFPerson类
(lldb) x/4gx 0x0000000102e2d648
0x102e2d648: 0x00000001f65e60b0 0x00000001f65e60b0
0x102e2d658: 0x00070002838e4c00 0x0003e03500000000
(lldb)  po 0x00000001f65e60b0 & 0x0000000ffffffff8ULL
NSObject

(lldb) p/x 0x00000001f65e60b0 & 0x0000000ffffffff8ULL
(unsigned long long) $15 = 0x00000001f65e60b0
通过第二个HFPerson类我们继续探索发现他的isa指针指向的是NSObject,而我们看到$15的地址跟原来一样,也就是说到顶了。

这边的NSObject是NSObejct类吗?
(lldb) p/x [NSObject class]
(Class) $17 = 0x00000001f65e60d8 NSObject

咦,发现$17 跟$15地址并不一样,所以上面的NSObject并不是我们所熟知的NSObject类,我们跟他取了一个名字叫\color{#f00}{根元类}
而上面的$13 跟 前面的$11不一样,我们将$13的HFPerson称之\color{#f00}{元类 }
通过上面的示例我们是不是可以得出这样的结论
对象isa->类isa->元类isa->NSObject(根元类)
等等刚刚HFPerson 继承 NSObject,如果有其他类继承HFPerson,那会有影响吗,我们再来实际考察一下

@interface HFStudent : HFPerson
@end
@interface HFPerson : NSObject
@end
HFPerson *p = [HFPerson alloc];
HFStudent *s = [HFStudent alloc];
NSLog(@"%@---%p", p, p); 断点到这里

(lldb) x/4gx s
0x281366340: 0x000001a10488562d 0x0000000000000000
0x281366350: 0x0000000000000000 0x0000000000000000
(lldb) po 0x000001a10488562d & 0x0000000ffffffff8ULL
HFStudent  (对象isa指针指向类,这个没错)

(lldb) p/x 0x000001a10488562d & 0x0000000ffffffff8ULL
(unsigned long long) $2 = 0x0000000104885628
(lldb) x/4gx 0x0000000104885628
0x104885628: 0x0000000104885600 0x0000000104885678
0x104885638: 0x00000001ae8bdb10 0x0000803900000000
(lldb) po 0x0000000104885600 & 0x0000000ffffffff8ULL
HFStudent (类的isa指针指向元类HFStudent)

(lldb) p/x 0x0000000104885600 & 0x0000000ffffffff8ULL
(unsigned long long) $4 = 0x0000000104885600
(lldb) x/4gx 0x0000000104885600
0x104885600: 0x00000001f65e60b0 0x0000000104885650
0x104885610: 0x00030002808703c0 0x0003e03500000000
(lldb) po 0x00000001f65e60b0 & 0x0000000ffffffff8ULL
NSObject (元类的isa指针指向的是根元类)

(lldb) p/x 0x00000001f65e60b0 & 0x0000000ffffffff8ULL
(unsigned long long) $6 = 0x00000001f65e60b0

这样就应该足够证明上面那个结论了
用一张图表示


D998832A-DF53-482C-BA04-AAE1E91260E8.png

元类

我们知道类有继承关系,元类是否也有呢?
同样我们还是用一个例子来说明


Class object_getClass(id obj)
{
    if (obj) return obj->getIsa();
    else return Nil;
}
object_getClass 获取的是对象的isa指向

    Class tMetaClass = object_getClass(HFStudent.class);
    NSLog(@"%@ meta - %p",tMetaClass,tMetaClass);
    Class tsuperClass = class_getSuperclass(tMetaClass);
    Class pMetaClass = object_getClass(HFPerson.class);
    NSLog(@"%@ meta - %p",pMetaClass,pMetaClass);
    NSLog(@"%@ - %p",tsuperClass,tsuperClass);
    Class psuperClass = class_getSuperclass(tsuperClass);
    Class nMetaClass = object_getClass(NSObject.class);
    NSLog(@"%@ meta- %p",nMetaClass,nMetaClass);
    NSLog(@"%@ - %p",psuperClass,psuperClass);
    Class rsuperClass = class_getSuperclass(psuperClass);
    NSLog(@"%@ - %p",rsuperClass,rsuperClass);
    Class prsuperClass = class_getSuperclass(rsuperClass);
    NSLog(@"%@ - %p",prsuperClass,prsuperClass);

2021-06-19 16:23:20.349082+0800 StoreKitDemo[86485:3135162] HFStudent meta - 0x1053e7698
2021-06-19 16:23:20.349244+0800 StoreKitDemo[86485:3135162] HFPerson meta - 0x1053e76e8
2021-06-19 16:23:20.349344+0800 StoreKitDemo[86485:3135162] HFPerson - 0x1053e76e8
2021-06-19 16:23:20.349440+0800 StoreKitDemo[86485:3135162] NSObject meta- 0x7fff89c111d8
2021-06-19 16:23:20.349540+0800 StoreKitDemo[86485:3135162] NSObject - 0x7fff89c111d8
2021-06-19 16:23:20.349626+0800 StoreKitDemo[86485:3135162] NSObject - 0x7fff89c11200
2021-06-19 16:23:20.349721+0800 StoreKitDemo[86485:3135162] (null) - 0x0

  1. 首先获取了HFStudent的元类tMetaClass,通过class_getSuperclass获取到tMetaClass的父类为tsuperClass(HFPerson元类),然后继续通过class_getSuperclass获取tsuperClass的父类psuperClass(NSObject 根元类),在继续通过class_getSuperclass获取psuperClass的父类为rsuperClass(也是NSObject,但是从地址上看并不是根元类,是NSObject 根类),继续class_getSuperclass获取rsuperClass的父类结果为nil
    从结果可以看出元类也是有继承关系,从而得出下图结论


    39778AC7-7A4B-4D19-9582-99D613D400CF.png

结合上面两个结论我们可以得出苹果之前给的一张isa和继承关系图


EFDA4984-323B-41F0-B102-6B7212ED9652.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,509评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,806评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,875评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,441评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,488评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,365评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,190评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,062评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,500评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,706评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,834评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,559评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,167评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,779评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,912评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,958评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,779评论 2 354

推荐阅读更多精彩内容