之前写过一篇《Runtime的初步认识》,读过的小伙伴们应该对OC中的类与C中的结构体的关系有了一定的了解。这篇文章就先介绍一下OC中的方法是如何“调用”的。这就是OC的另一个机制——消息机制。
OC 的消息机制是指,在外部需要执行某个对象的方法时,使用的方式是“发送消息”而不是“调用”。
在学 Runtime 之前你绝对不理解为什么是发送消息而不是调用。“调用”时确定的,而最终要执行哪段代码是不确定的。
有可能现在还不懂这个确定不确定的到底是什么意思。这个问题暂时可以先留着,我们先看看我们的方法“调用”在runtime转化成C或C++的时候到底变成什么样子了。
首先我们新建一个Mac OS X 命令行工程(这个在我们学习OC之前学习C的时候有可能用到过的)
这里创建一个命令行工程完全是为了简单。
这样我们就获得了一个main.m
文件
然后我们在main.m
文件中写一句最简单的实例化对象的代码
id object = [NSObject alloc];
object = [obj init];
保存一下之后用终端cd到这个文件目录下(此处可以打开终端,输入cd空格之后把那个文件夹拖入终端自动生成路径按回车~)
然后执行clang
编译命令把main.m
文件编译成C++
clang -rewrite-objc main.m
然后你就可以得到一个 main.cpp 文件,这就是 C++ 文件了。
打开这个文件,到文件的最后,你可以找到你写的 main 函数,看看它有什么内容
id object = ((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSObject"), sel_registerName("alloc"));
object = ((id (*)(id, SEL))(void *)objc_msgSend)((id)object, sel_registerName("init"));
似乎看不太懂,所以要简化一下(去掉一些属性声明,不影响实际逻辑)
id object = objc_msgSend(objc_getClass("NSObject"), sel_registerName("alloc"));
object = objc_msgSend(object, sel_registerName("init"));
与OC代码对应就是
id object = [NSObject alloc];
//编译成C++后
id object = objc_msgSend(objc_getClass("NSObject"), sel_registerName("alloc"));
object = [object init];
//编译成C++后
object = objc_msgSend(object, sel_registerName("init"));
这里
objc_getClass("NSObject")
通过字符串获取Class
sel_registerName("init")
通过字符串获取方法SEL
objc_msgSend(id, SEL)
消息发送的方法
- 首先通过一个字符串创建一个类的结构体指针
- 然后通过一个字符串创建一个类方法的结构体指针
- 最后向类结构体发送一个消息,得到一个结果。
这就是一个最简单的消息机制,把面向对象变为面向过程。
时间: 2024-11-10 02:26:04