Runtime01 类与元类

来看一张经典的描述 isasuperclass 指向的图。

从这我们可以看到:

isa

  • instance的isa指向class
  • class的isa指向meta-class
  • meta-class的isa指向基类的meta-class

superclass

  • class的superclass指向父类的class
    如果没有父类,superclass指针为nil
  • meta-class的superclass指向父类的meta-class
    基类的meta-class的superclass指向基类的class

方法调用

  • instance调用对象方法的轨迹
    isa找到class,方法不存在,就通过superclass找父类
  • class调用类方法的轨迹
    isa找meta-class,方法不存在,就通过superclass找父类

下面通过代码来确定一下

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43

@interface Person: NSObject
@end
...

void test1() {
NSLog(@"NSObject class:%p metaclass:%p", [NSObject class], object_getClass([NSObject class]));

Person *person = [[Person alloc] init];
Class cls = person;
int i = 0;
while (i < 4) {
NSLog(@"class:%p metaclass:%p", cls, object_getClass(cls));
cls = object_getClass(cls);
i++;
}

}

输出信息:

NSObject class:0x7fff991bd118 metaclass:0x7fff991bd0f0
---> 说明 NSObject 的isa 确实指向它的元类

class:0x100659b60 metaclass:0x100002100
---> 说明 person对象的 isa 指向 Person类对象

class:0x100002100 metaclass:0x1000020d8
---> 说明 Peson类对象的 isa 指向 Person元对象

class:0x1000020d8 metaclass:0x7fff991bd0f0
---> 说明 Peson元类对象的 isa 指向 NSObject元类对象

class:0x7fff991bd0f0 metaclass:0x7fff991bd0f0
---> 说明 NSObject元类对象 isa 指向 NSObject元类对象

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

我们再看一下 objc_allocateClassPair 方法内部实现

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes)
{
Class cls, meta;

rwlock_writer_t lock(runtimeLock);

// Fail if the class name is in use.
// Fail if the superclass isn't kosher.
if (getClass(name) || !verifySuperclass(superclass, true/*rootOK*/)) {
return nil;
}

// Allocate new classes.
cls = alloc_class_for_subclass(superclass, extraBytes); //分配
meta = alloc_class_for_subclass(superclass, extraBytes);

// fixme mangle the name if it looks swift-y?
objc_initializeClassPair_internal(superclass, name, cls, meta);

return cls;
}

static void objc_initializeClassPair_internal(Class superclass, const char *name, Class cls, Class meta)
{
runtimeLock.assertWriting();

class_ro_t *cls_ro_w, *meta_ro_w;

// 初始化cls和meta的大小和数据
cls->setData((class_rw_t *)calloc(sizeof(class_rw_t), 1));
meta->setData((class_rw_t *)calloc(sizeof(class_rw_t), 1));

...

cls_ro_w->flags = 0; // 普通类
meta_ro_w->flags = RO_META; // 标记为meta

...

// Connect to superclasses and metaclasses
cls->initClassIsa(meta); // 将cls的isa指向meta
if (superclass) {
meta->initClassIsa(superclass->ISA()->ISA()); // meta的isa指向根类的meta
cls->superclass = superclass;
meta->superclass = superclass->ISA(); //// meta的父类为父类的meta
addSubclass(superclass, cls);
addSubclass(superclass->ISA(), meta);
} else {
meta->initClassIsa(meta); // 根类的isa指向自己
cls->superclass = Nil;
meta->superclass = cls; // 根类的父类指向cls
addRootClass(cls);
addSubclass(cls, meta);
}

....
}


-------------The End-------------

本文标题:Runtime01 类与元类

文章作者:kysonyangs

发布时间:2018年06月23日 - 15:06

最后更新:2020年05月16日 - 13:05

原始链接:https://kysonyangs.github.io/default/Runtime01_类与元类/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。