1-5.【OC】【基础】为什么 Objective-C 被称为“运行时语言”?

2 阅读3分钟

说 Objective-C 是一门“运行时语言”(Runtime-based Language),本质上是因为它把决策权从编译阶段推迟到了执行阶段。

在 C++ 或 Java 等语言中,很多事情在代码写完、编译器跑完的那一刻就“写死”了;而在 Objective-C 里,编译器只是个“传话筒”,真正的表演要在程序运行起来后才开始。

以下是支撑这一称呼的三个核心支柱:


1. 动态绑定 (Dynamic Binding)

在传统的静态语言中,调用一个方法就像是拨打一个分机号,线路在编译时就插好了。但在 Objective-C 中,调用方法是发送消息

当你写下 [obj doSomething] 时:

  • 编译期: 编译器只是简单地将其转换为 objc_msgSend(obj, @selector(doSomething))。它并不确定 obj 是否真的有这个方法,只要它看到声明了,就放行。
  • 运行时: 只有程序跑到了这一行,系统才会通过 objisa 指针找到它的类,然后在类的方法列表中查找 doSomething

这意味着你可以在运行时动态地更换 obj 指向的对象类型,或者给类动态增加方法,程序依然能跑通。


2. 消息转发机制 (Message Forwarding)

如果一个对象收到了它无法响应的消息,在其他语言中程序会立即崩溃。但 Objective-C 的运行时给了对象三次自救机会

  1. 动态方法解析: 运行时问你:“要不要临时加个方法实现?”
  2. 备援接收者: 运行时问你:“你处理不了,要不要把这活儿转交给别的对象做?”
  3. 完全消息转发: 运行时把消息包装成 NSInvocation 对象,让你像处理数据一样处理这个“动作”。

这种“边跑边商量”的特性,是 Objective-C 能够实现类似 AOP(面向切面编程)热修复(Hotfix) 的底层基础。


3. 内省与反射 (Introspection & Reflection)

Objective-C 具有极其强大的自我察觉能力。在运行时,程序可以“询问”对象:

  • isKindOfClass: 你是不是某个类或其子类的实例?
  • respondsToSelector: 你能不能响应这个方法?
  • conformsToProtocol: 你有没有遵守这个协议?

甚至,你可以通过 Method Swizzling(黑魔法),在运行时交换两个方法的具体实现(IMP)。这在不修改原有类源代码的情况下,能极大地改变程序的行为。


4. Runtime 库:幕后黑手

这一切的背后,是一个用 C 和汇编编写的动态库——Objective-C Runtime

所有的 Objective-C 对象在底层都是 C 语言的结构体:

struct objc_object { Class isa; };struct\ objc\_object\ \{ \ Class\ isa;\ \};

因为有了这个 isa 指针,每个对象在运行时都能找到自己的身份证明(类对象)。类对象里记录了方法列表、属性列表和协议列表。


总结

“运行时语言”意味着:

  • 灵活性: 可以在程序运行期间修改类结构、交换方法、动态添加属性。
  • 弱化编译约束: 编译器不再是绝对的权威,它更像是一个建议者。
  • 高度动态的 UI 交互: 这也是为什么早期的 iOS 开发中,Delegate、Target-Action 等模式如此盛行的原因,因为它们高度依赖这种动态分发。