# 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](/files/-McsVJo4418GcI35qPDN)

* *\_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](/files/-McsVJo5apYfPuj0xgc5)

> 子类实例对象 `-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](/files/-McsVJo6aqmVWkfIAsdz)

> 实例对象 `-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](/files/-McsVJo789EC0IXsiW_L)

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

### 3.4 ISA关系图

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

![ISA](/files/-McsVJo8Plx8GXIuebuJ)

### 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](/files/-McsVJo9o8CN7zFrTv6H)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ryukiedev.gitbook.io/wiki/ios/di-ceng/04.isa-yu-class.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
