[翻译]Objective-C内部探秘1:类架构

(原文出处:Objective-C Internals | Always Processing)

Objective-C有一个独特的类结构,其中类是对象。它的优雅设计允许通过使用编译器生成的元类对所有对象类型进行动态方法派发。

Objective-C,像许多流行的编程语言一样,采用基于类的面向对象编程风格。为了讨论Objective-C的类架构,我们将重点放在类的行为(方法和属性)上,暂时不涉及类的状态(即实例变量,在本文中不涉及)。

尽管属性提供了对类状态的访问,但在Objective-C中它们只是方法的语法糖。(这个话题可以在之后的文章里探讨🤣)

以下六行代码足以探索Objective-C的类架构:

scss 复制代码
@interface MyObject: NSObject
+ (void)classMethod;o
- (void)instanceMethod;
@end

MyObject *object = [[MyObject alloc] init];

方法派发

上述最后一行实例化了类MyObject,并将新的对象实例赋值给变量object。新的对象实例具有自己的状态,并且可以响应消息(即方法调用),例如-instanceMethod和-init。

Objective-C对每个消息发送(即每个方法调用)使用动态派发1。运行时通过在实例的isa变量所引用的类对象中查找选择器(即方法名)来找到方法实现。(所有Objective-C对象中的第一个实例变量是isa指针,它由编译器自动插入并由运行时初始化。)

前面段落中使用类对象这个术语是有意义的:在Objective-C中,类也是对象!这个巧妙的设计是类方法语言特性的基础(例如调用NSObject alloc或MyObject classMethod):它使得类方法可以完全多态(即子类可以重写类方法),并且消除了类方法和实例方法之间的运行时区别(类方法和实例方法都通过objc_msgSend进行派发)。

因为类也是对象,它们也有一个isa指针,指向元类。元类为类对象提供了选择器到类方法实现的映射,就像类对象为类实例(即对象)提供选择器到实例方法实现的映射一样。

继承

任何类或元类只为类实现的方法提供选择器到方法实现的映射。在上面的代码示例中,MyObject的类对象具有instanceMethod的映射,而MyObject的元类具有classMethod的映射。

MyObject还响应于+alloc和-init,这些方法在NSObject中实现。每个类对象(包括每个元类)都有一个指向其超类的引用。在解析选择器时,如果类/元类对象没有定义映射,运行时会在下一个超类中搜索定义。(尽管运行时提供了对异常的处理方法,但如果在超类链的末尾找不到定义,运行时仍将抛出异常。)

架构图

下面的图示说明了上面讨论的Objective-C类的设计:

对象实例有一个isa变量,指向MyClass类对象。

MyClass类对象有:

  • 一个isa变量,指向MyClass元类。
  • 一个super变量,指向NSObject类对象。

MyClass元类有:

  • 一个isa变量,指向NSObject(根对象)元类。
  • 一个super变量,指向NSObject元类。

图中还显示了一些上述讨论未涵盖的细节:

  • 每个元类的isa变量都指向根对象的元类,包括根对象元类本身。isa变量不为nil是有意义的(对象必须有某种类型),但我不确定为什么所有元类的类型都是根元类的类型,而不是运行时提供的类型。不过,实际上这并不重要,因为元类本身永远不会接收消息。
  • 根元类的超类是根类对象。当我在研究图示时,这一点让我感到惊讶。我一开始并没有明确地理解为什么会存在这个链接,我认为它的超类会是nil。
相关推荐
老李IT笔记5 小时前
设备指纹由哪几个字段拼出来:换一块主板会变成新设备
ios·智能手机
andyweike5 小时前
iOS App 测试
ios·测试·ad hoc·分发
茶底世界之下15 小时前
花瓣要更柔和,还是更有反差?用 Awaking 做一次对比度取舍
ios
Anhty1 天前
2026最新免费手机音频处理工具 !!
android·功能测试·ios·智能手机·音视频
2501_915909061 天前
iOS应用从开发到上架App Store的完整发布流程与步骤指南
android·ios·小程序·https·uni-app·webview
初雪云2 天前
UniApp 云打包拿到 IPA 后,真正的发布工作才刚开始
ios·自动化·编辑器·产品经理·iphone
Lancker2 天前
没有 Mac 也能上架 iOS:GitHub Actions 全自动构建 + 签名 + TestFlight 送审实录
macos·ios·github
茶底世界之下2 天前
晚霞要多暖?用 Awaking 只改色温做一次取舍
ios
酒神dnspup2 天前
多地区网站可用性监控怎么做?DNSPup 从基线到告警的完整实战
运维·ios·云计算·iphone·dns·网络监控
福兮说2 天前
浏览器里把 iPhone 的 HEIC 转成 JPG:Chrome 解不开、转完大了七成、拍摄时间全丢,六个坑实测
前端·javascript·图像处理·chrome·ios·iphone·heic