ProtocalKit 解析

在 GitHub 上面看到的这个项目,类可以通过 protocol 继承其方法。感觉很好奇,于是就研究了一下其代码,代码不多,但是思路很好~

项目地址: ProtocalKit

使用方式见: README.md

作者思路

作者通过一个关键字 @defs(Forkable),创建了一个临时类,临时类实现了 Forkable 这个协议,所以 fork 和 github 的实现代码其实是在这个临时类里面的。

然后作者定义了一个结构体:

typedef struct {
Protocol *__unsafe_unretained protocol;
Method *instanceMethods;
unsigned instanceMethodCount;
Method *classMethods;
unsigned classMethodCount;
} PKExtendedProtocol;

在临时类load时,把这个类里面的所有方法加到Forkable这个协议对应的结构体的方法列表里面。

然后作者建了一个结构体数组

static PKExtendedProtocol *allExtendedProtocols = NULL;

用来存放所有的 protocol,以及其实现方法。

以上工作完成之后 allExtendedProtocols 就初始化完成了,所有的 protocol 以及其 Method 全部存放在这个数组里面。

接下来,把 allExtendedProtocols 里面的所有方法,加入到实现这个 protocol 的类的方法列表里面去,实例方法加入到本类的 objc_method_list 里面,类方法就加入到 MetaClass 的 objc_method_list 里面去。如果类本身实现了协议方法,就不会加入。

这样就间接的把临时类里面的 protocol 实现方法,加入到实现了这个协议的类的方法列表里面去了。

第一步生成 allExtendedProtocols 数组,作者是在 load 方法里面进行的,也就是说在执行之前,引入这个类的时候就会生成 allExtendedProtocols 数组。

第二步把 allExtendedProtocols 里面的方法加入到实现协议的类里面,作者通过 __attribute__((constructor)) 这个属性,在 main 函数被调用之前调用。然后作者通过一个互斥锁来保证这两步的先后顺序,即在第二步执行前 allExtendedProtocols 数组已经初始化完成。

注释代码

添加注释后的代码已上传 GitHub 请前往下载阅读

下载地址: ProtocalKit-注释版