Category

1. 初次见面

Category是Objective-C 2.0之后添加的语言特性,Category的主要作用是为已经存在的类添加方法。除此之外,Apple还推荐了Category的另外两个使用场景(详见 1):

  • 可以把类的实现分开在几个不同的文件里面。这样做有几个显而易见的好处:
  1. 可以减少单个文件的体积

  2. 可以把不同的功能组织到不同的Category里

  3. 可以由多个开发者共同完成一个类

  4. 可以按需加载想要的Category 等等

  • 声明私有方法

不过除了apple推荐的使用场景,广大开发者脑洞大开,还衍生出了Category的其他几个使用场景:

  • 模拟多继承
  • 把framework的私有方法公开

Objective-C的这个语言特性对于纯动态语言来说可能不算什么,比如javascript,你可以随时为一个“类”或者对象添加任意方法和实例变量。但是对于不是那么“动态”的语言而言,这确实是一个了不起的特性。

2. 与Extension的区别

Extension看起来很像一个匿名的Category,但是Extension和有名字的Category几乎完全是两个东西。

Extension在编译期决议,它就是类的一部分。在编译期和头文件里的@interface以及实现文件里的@implement一起形成一个完整的类,它伴随类的产生而产生,亦随之一起消亡。

Extension一般用来隐藏类的私有信息,你必须有一个类的源码才能为一个类添加Extension,所以你无法为系统的类比如NSString添加Extension。(详见 2

但是Category则完全不一样,它是在运行期决议的。

CategoryExtension的区别来看,我们可以推导出一个明显的事实,Extension可以添加实例变量,而Category是无法添加实例变量的(因为在运行期,对象的内存布局已经确定,如果添加实例变量就会破坏类的内部布局,这对编译型语言来说是灾难性的)。

3. 揭开面纱

我们知道,所有的OC类和对象,在runtime层都是用struct表示的,Category也不例外,在runtime层,Category用结构体category_t(在objc-runtime-new.h中可以找到此定义),它包含了:

  1. 类的名字(name)
  2. 类(class)
  3. Category中所有给类添加的实例方法的列表(instanceMethods)
  4. Category中所有添加的类方法的列表(classMethods)
  5. Category实现的所有协议的列表(protocols)
  6. Category中添加的所有属性(instanceProperties)

results matching ""

    No results matching ""