MST

星途 面试题库

面试题:Objective-C扩展与类别在运行时内存布局的差异

说明Objective-C扩展(Extension)和类别在运行时内存布局上有什么不同,这种不同对它们的特性和使用场景有何影响。
20.6万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

运行时内存布局不同

  1. 类别(Category)
    • 在运行时,类别是在运行时动态加载的。它主要是为已有的类添加新的方法,并不改变类的原有的内存布局。类别中的方法被存储在一个单独的结构体中,在运行时会被合并到类的方法列表里。
    • 类别没有实例变量(虽然可以通过关联对象来模拟添加实例变量的效果)。因为不改变类的内存布局,所以不能添加实例变量,这是为了保证类别在运行时添加方法的同时,不影响原有类的内存布局和对象创建的稳定性。
  2. 扩展(Extension)
    • 扩展实际上是一种特殊的匿名类别,它在编译期就被添加到类中。扩展定义的方法会和类的原有方法一起被编译到类的方法列表中,从运行时内存布局角度看,它与类的原有方法在存储结构上没有本质区别。
    • 扩展可以声明实例变量,这些实例变量会在类的内存布局中分配空间,就如同在类的@interface声明中定义的实例变量一样。这意味着扩展中的实例变量是类的对象内存布局的一部分。

对特性和使用场景的影响

  1. 类别(Category)
    • 特性
      • 主要用于为现有类添加方法,无需访问类的源代码,方便在不改变原有类定义的情况下增加功能。由于不增加实例变量,适合做一些功能性的扩展,如为系统类添加便捷方法。
      • 多个类别中如果有同名方法,最后加载的类别中的方法会覆盖之前加载的类别中的同名方法(这可能会导致意外行为,需要注意)。
    • 使用场景
      • 为系统类添加自定义功能,例如为NSString类添加计算字符串中特定字符数量的方法。
      • 对大型类进行功能模块划分,将不同功能的方法分散到不同类别中,增强代码的可读性和维护性,比如一个复杂的UIViewController类,可将视图布局相关方法放在一个类别,数据处理方法放在另一个类别。
  2. 扩展(Extension)
    • 特性
      • 因为可以声明实例变量,所以可以为类增加私有实例变量和私有方法(虽然在Objective - C中没有真正的私有概念,但扩展中的方法和变量相对更难被外部访问)。
      • 由于在编译期就融入类,与类的原有部分紧密结合,安全性和稳定性较高。
    • 使用场景
      • 实现类的私有方法和私有变量,例如在一个自定义的MyClass类的扩展中声明私有实例变量来保存一些内部状态,声明私有方法来处理内部逻辑,这些私有内容对外部类不可见。
      • 对类进行内部扩展,在类的实现文件中使用扩展来补充一些只有类自身实现中会用到的方法和变量,保持类的接口简洁。