# 04.ISA与Class

> 本文基于 `objc4-818.2` 源码
>
> 本文较长，建议吃饱喝足再进行阅读。由于很多内容关联性很强，本来准备拆分一下的。但还是决定放在一起，逐步深入。避免发生 `这里一个知识点在另一篇文章，那我晚点再看（根本不会再看）` 的情况。
>
> 其中 `协议列表` 的探究过程中遇到了一些问题，无法进行下去，有解决办法的欢迎交流\~

## 一、类对象

在上一文中我们初步探究了，obj和isa.

通过下面的步骤我们可以找到类对象

```cpp
(lldb) p/x obj1
(RYObject *) $8 = 0x000000028026c340
(lldb) x/4gx 0x000000028026c340
0x28026c340: 0x000001a1042194f1 0x0000000000000000
0x28026c350: 0x0000b6106e0ac350 0x000000028356012e
(lldb) p/x 0x000001a1042194f1 & 0x0000000ffffffff8ULL
(unsigned long long) $14 = 0x00000001042194f0
(lldb) po 0x000001a1042194f1 & 0x0000000ffffffff8ULL
RYObject
```

### 1.1 类对象ISA

Class其实也是一个对象，那么我很好奇。类对象是不是也有个ISA呢？

我们以同样的步骤进行调试：

```cpp
(lldb) p/x 0x000001a1042194f1 & 0x0000000ffffffff8ULL
(unsigned long long) $11 = 0x00000001042194f0
(lldb) x/4gx 0x00000001042194f0
0x1042194f0: 0x00000001042194c8 0x00000001fc942218
0x104219500: 0x00030002815641c0 0x0003801000000000
(lldb) po 0x00000001042194c8
RYObject
```

居然也有一个`RYObject`，并且内存地址和第一步生成的`0x00000001042194f0` 不一样，是`0x00000001042194c8`。

这里的`0x00000001042194c8`其实就是`元类`。

## 二、元类

我们将刚才编译过的`MachO`丢进`MachoView`中解析。

打开符号表，搜索`RYObject`：

![1](https://4193904735-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MI8JgbGh3U6X_oedqkm%2Fsync%2F2b897f2568359a8afa4ad73b688fb469a3ef6a87.png?generation=1624445644763991\&alt=media)

* _\_OBJC\_METACLASS\_RO_$\_RYObject
  * 元类
* _\_OBJC\_CLASS\_RO_$\_RYObject
  * 类

## 三、ISA与Class的关系

我们使用下面的代码进行验证，其中`RYSubObject`继承`RYObject`

```cpp
    RYObject *rySubObject = [[RYSubObject alloc] init];
    NSLog(@"实例%@ 的地址是 %p", rySubObject, rySubObject);
    Class rySubObjectClass = object_getClass(rySubObject);
    NSLog(@"实例%@ 的类对象是 %@ 地址是 %p", rySubObject, rySubObjectClass, rySubObjectClass);
    Class rySubObjectMetaClass = object_getClass(rySubObjectClass);
    NSLog(@"实例%@ 的元类是 %@ 地址是 %p", rySubObject, rySubObjectMetaClass, rySubObjectMetaClass);
    Class rySubObjectRootMetaClass = object_getClass(rySubObjectMetaClass);
    NSLog(@"实例%@ 的根元类是 %@ 地址是 %p", rySubObject, rySubObjectRootMetaClass, rySubObjectRootMetaClass);

    NSLog(@"\n");

    RYObject *ryObject = [[RYObject alloc] init];
    NSLog(@"实例%@ 的地址是 %p", ryObject, ryObject);
    Class ryObjectClass = object_getClass(ryObject);
    NSLog(@"实例%@ 的类对象是 %@ 地址是 %p", ryObject, ryObjectClass, ryObjectClass);
    Class ryObjectMetaClass = object_getClass(ryObjectClass);
    NSLog(@"实例%@ 的元类是 %@ 地址是 %p", ryObject, ryObjectMetaClass, ryObjectMetaClass);
    Class ryObjectRootMetaClass = object_getClass(ryObjectMetaClass);
    NSLog(@"实例%@ 的根元类是 %@ 地址是 %p", ryObject, ryObjectRootMetaClass, ryObjectRootMetaClass);

    NSLog(@"\n");

    NSObject *nsObject = [[NSObject alloc] init];
    NSLog(@"实例%@ 的地址是 %p", nsObject, nsObject);
    Class nsObjectClass = object_getClass(nsObject);
    NSLog(@"实例%@ 的类对象是 %@ 地址是 %p", nsObject, nsObjectClass, nsObjectClass);
    Class nsObjectMetaClass = object_getClass(nsObjectClass);
    NSLog(@"实例%@ 的元类是 %@ 地址是 %p", nsObject, nsObjectMetaClass, nsObjectMetaClass);
    Class nsObjectRootMetaClass = object_getClass(nsObjectMetaClass);
    NSLog(@"实例%@ 的根元类是 %@ 地址是 %p", nsObject, nsObjectRootMetaClass, nsObjectRootMetaClass);

    NSLog(@"\n");

    Class rySubSuperClass = class_getSuperclass(rySubObjectClass);
    NSLog(@"子类%@（地址%p）的父类是%@ 地址是%p",rySubObjectClass,rySubObjectClass, rySubSuperClass, rySubSuperClass);
    Class rySuperClass = class_getSuperclass(ryObjectClass);
    NSLog(@"父类%@（地址%p）的父类是%@ 地址是%p",ryObjectClass,ryObjectClass, rySuperClass, rySuperClass);
    Class nsSuperClass = class_getSuperclass(nsObjectClass);
    NSLog(@"根类%@（地址%p）的父类是%@ 地址是%p",nsObjectClass,nsObjectClass, nsSuperClass, nsSuperClass);

    NSLog(@"\n");

    Class rySubMetaSuperClass = class_getSuperclass(rySubObjectMetaClass);
    NSLog(@"元类%@（地址%p）的父类是%@ 地址是%p",rySubObjectMetaClass,rySubObjectMetaClass, rySubMetaSuperClass, rySubMetaSuperClass);
    Class ryMetaSuperClass = class_getSuperclass(ryObjectMetaClass);
    NSLog(@"元类%@（地址%p）的父类是%@ 地址是%p",ryObjectMetaClass,ryObjectMetaClass, ryMetaSuperClass, ryMetaSuperClass);
    Class nsMetaSuperClass = class_getSuperclass(nsObjectMetaClass);
    NSLog(@"根元类%@（地址%p）的父类是%@ 地址是%p",nsObjectMetaClass,nsObjectMetaClass, nsMetaSuperClass, nsMetaSuperClass);
```

依次得到输出如下

### 3.1 子类ISA

```cpp
2021-06-22 21:21:53.685253+0800 Class[15467:5499656] 实例<RYSubObject: 0x282af0700> 的地址是 0x282af0700
2021-06-22 21:21:53.685426+0800 Class[15467:5499656] 实例<RYSubObject: 0x282af0700> 的类对象是 RYSubObject 地址是 0x10227d648
2021-06-22 21:21:53.685717+0800 Class[15467:5499656] 实例<RYSubObject: 0x282af0700> 的元类是 RYSubObject 地址是 0x10227d620
2021-06-22 21:21:53.685782+0800 Class[15467:5499656] 实例<RYSubObject: 0x282af0700> 的根元类是 NSObject 地址是 0x1fc9421f0
```

![RYSubObject](https://4193904735-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MI8JgbGh3U6X_oedqkm%2Fsync%2F96375633209b56b4d495a452e077e54cb3416ad1.png?generation=1624445643706612\&alt=media)

> 子类实例对象 `-isa-` 子类 `-isa-` 子类元类 `-isa-` 根元类

### 3.2 父类ISA

```cpp
2021-06-22 21:21:53.685876+0800 Class[15467:5499656] 实例<RYObject: 0x282afc490> 的地址是 0x282afc490
2021-06-22 21:21:53.685929+0800 Class[15467:5499656] 实例<RYObject: 0x282afc490> 的类对象是 RYObject 地址是 0x10227d5a8
2021-06-22 21:21:53.686703+0800 Class[15467:5499656] 实例<RYObject: 0x282afc490> 的元类是 RYObject 地址是 0x10227d580
2021-06-22 21:21:53.686760+0800 Class[15467:5499656] 实例<RYObject: 0x282afc490> 的根元类是 NSObject 地址是 0x1fc9421f0
```

![RYObject](https://4193904735-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MI8JgbGh3U6X_oedqkm%2Fsync%2F713bb86d0bc404a8041b91c762fe0083f0d1ef27.png?generation=1624445642714585\&alt=media)

> 实例对象 `-isa-` 类 `-isa-` 元类 `-isa-` 根元类

### 3.3 根类ISA

```cpp
2021-06-22 21:21:53.687198+0800 Class[15467:5499656] 实例<NSObject: 0x282afdae0> 的地址是 0x282afdae0
2021-06-22 21:21:53.687245+0800 Class[15467:5499656] 实例<NSObject: 0x282afdae0> 的类对象是 NSObject 地址是 0x1fc942218
2021-06-22 21:21:53.687291+0800 Class[15467:5499656] 实例<NSObject: 0x282afdae0> 的元类是 NSObject 地址是 0x1fc9421f0
2021-06-22 21:21:53.687384+0800 Class[15467:5499656] 实例<NSObject: 0x282afdae0> 的根元类是 NSObject 地址是 0x1fc9421f0
```

![NSObject](https://4193904735-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MI8JgbGh3U6X_oedqkm%2Fsync%2F547f69c7003dd8b90e9e24b5c66424b854b151b3.png?generation=1624445639694335\&alt=media)

> 根类实例对象 `-isa-` 根类 `-isa-` 根元类 `-isa-` 根元类

### 3.4 ISA关系图

我们将上面的三组关系整合一下

![ISA](https://4193904735-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MI8JgbGh3U6X_oedqkm%2Fsync%2Fc1c51faa55834b7592a362705e2fa03383f8a4f4.png?generation=1624445640672238\&alt=media)

### 3.5 类继承关系

```cpp
2021-06-22 21:21:53.687691+0800 Class[15467:5499656] 子类RYSubObject（地址0x10227d648）的父类是RYObject 地址是0x10227d5a8
2021-06-22 21:21:53.687822+0800 Class[15467:5499656] 父类RYObject（地址0x10227d5a8）的父类是NSObject 地址是0x1fc942218
2021-06-22 21:21:53.688283+0800 Class[15467:5499656] 根类NSObject（地址0x1fc942218）的父类是(null) 地址是0x0
```

> 子类 `-继承-` 父类 `-继承-` 根类 `-继承-` 空

### 3.6 元类继承关系

```cpp
2021-06-22 21:21:53.688982+0800 Class[15467:5499656] 元类RYSubObject（地址0x10227d620）的父类是RYObject 地址是0x10227d580
2021-06-22 21:21:53.689029+0800 Class[15467:5499656] 元类RYObject（地址0x10227d580）的父类是NSObject 地址是0x1fc9421f0
2021-06-22 21:21:53.689075+0800 Class[15467:5499656] 根元类NSObject（地址0x1fc9421f0）的父类是NSObject 地址是0x1fc942218
```

这里发现 _**根元类NSObject（地址0x1fc9421f0）**_ 的父类是 _**根类（地址0x1fc942218）**_

> 子类的元类 `-继承-` 父类的元类 `-继承-` 根元类 `-继承-` 根类

### 3.7 ISA与Class的继承关系图梳理

![ISA与Class](https://4193904735-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MI8JgbGh3U6X_oedqkm%2Fsync%2Fdf45507ca82fb53fe2244a4351491d082f284c0d.png?generation=1624445638728485\&alt=media)
