一、Category 分类
在面对一个类定义时,可能想要添加一些新方法,例如对于 Fraction(分数)类,除了将两个分数相加的 add:方法之外,还想要将两个分数相减、相乘和相除的方法。另外,当参与一个大型程序设计项目,为一个新定义的类编写处理文件系统的方法,并使其模块化。
以上情况的实用解决方案就是使用分类 Category。
- 分类提供了一种简单的方式,将类的定义模块化到相关方法的组或分类中。
- 分类提供了扩展现有类定义的简便方式,不必访问类的源代码,也无需创建子类。
- 可以通过未命名分类实现私有方法
以上例子中,以为 Fraction 添加新方法为例,新的 MathOps 分类的接口部分代码如下:
#import "Fraction.h"
@interface Fraction (MathOps)
-(Fraction*) add:(Fraction*) f;
-(Fraction*) mul:(Fraction*) f;
-(Fraction*) sub:(Fraction*) f;
-(Fraction*) div:(Fraction*) f;
@end
- 这即是接口部分的定义,也是现有接口部分的扩展,因此需要包括原始接口部分
- @interface Fraction (MathOps) 告诉编译器正在为 Fraction 类定义名为 MathOps 的分类
- 实现部分与接口部分相同,通过将分类名称放在类名称之后的圆括号中确定方法所属的分类 @implement Fraction (MathOps)
依照惯例,作为分类的 .h 和 .m 文件的基本名称由类名加分类名组成-FractionMathOps。
category只能给某个已有的类扩充方法,不能扩充成员变量。category中也可以添加属性,不过@property只会生成setter和getter的声明,不会生成setter和getter的实现以及成员变量。
如果category中的方法和类中原有方法同名,运行时会优先调用category中的方法。也就是,category中的方法会覆盖掉类中原有的方法。
iOS Category详解 https://www.jianshu.com/p/c92b17a36b9e
二、Extension 扩展
Extension 看起来像一个匿名的 category,和 category 不同的是 extension 不但可以声明方法,还可以声明属性、成员变量。extension 一般用于声明 私有方法、私有属性和私有成员变量。
- 类扩展实现的数据和方法都是私有的,数据和方法仅供这个类本身实用。
- 类扩展只存在与一个 .h 文件中或者寄生于一个类的 .m 文件中。
#import "Fraction.h"
@interface Fraction ( )
@property (nonatomic) unsigned int officeAlarmCode;
-(Fraction*) mul:(Fraction*) f;
@end
@implementation Employee
....
创建一个未命名的分类,且在()之间不指定名字。未命名的分类中声明的方法需要在主实现区域实现,而不是在分离的实现区域中实现。
三、Category 与 Extension 的区别
- extension 在编译期决议(成为类的一部分),category 在运行时决议。
extension在编译期和头文件里的@interface以及实现文件里的@implement一起形成一个完整的类,extension伴随类的产生而产生,亦随之一起消亡。
- extension 可以添加实例变量,而 category 无法添加实例变量。
因为在运行期,对象的内存布局已经确定,如果添加实例变量就会破坏类的内部布局,这对编译型语言来说是灾难性的。
- extension和category都可以添加属性,但是category的属性不能生成成员变量和getter、setter方法的实现。
- category可以给系统提供的类添加分类,使之模块化。
- extension一般用来隐藏类的私有信息,无法直接为系统的类扩展,但可以先创建系统类的子类再添加extension。