类别(Category)主要有3个作用:
将类的实现分散到多个不同文件或多个不同框架中。
创建对私有方法的前向引用。
向对象添加非正式协议。
声明:@interface 类名(分类名称) @end
实现:@implementation 类名(分类名称) @end
注意:
(1)在分类只能增加方法,不能增加成员变量,如果要增加成员变量的话该考虑用继承去实现
(2)在分类实现方法中可以访问类中的成员变量但是不能访问类中的属性@property
(3)在分类中可以重新实现原类中的方法,但会将原类中的方法覆盖而失效。
因为在执行对象成员方法的时候会优先去分类中查找,然后再去原类中去查找,最后去父类中去查找
(4)如果一个类有多个分类,而且分类中有同名的方法那么最后编译的分类会将前面编译的分类覆盖而执行输出
// 另外一份解释来自《招聘一个靠谱的 iOS》—参考答案(上)---24
// 类方法:
- 类方法是属于类对象的
- 类方法只能通过类对象调用
- 类方法中的self是类对象
- 类方法可以调用其他的类方法
- 类方法中不能访问成员变量
- 类方法中不能直接调用对象方法
// 实例方法:
- 实例方法是属于实例对象的
- 实例方法只能通过实例对象调用
- 实例方法中的self是实例对象
- 实例方法中可以访问成员变量
- 实例方法中直接调用实例方法
- 实例方法中也可以调用类方法(通过类名)
4 运行时能增加成员变量么?能增加属性么?如果能,如何增加?如果不能,为什么?
Category中不能动态添加成员变量;
在Objective-C提供的runtime函数中,确实有一个class_addIvar()函数用于给类添加成员变量,但是阅读过苹果的官方文档的人应该会看到:
大概的意思说,这个函数只能在“构建一个类的过程中”调用。一旦完成类定义,就不能再添加成员变量了。经过编译的类在程序启动后就被runtime加载,没有机会调用addIvar。程序在运行时动态构建的类需要在调用objc_registerClassPair之后才可以被使用,同样没有机会再添加成员变量。
因为方法和属性并不“属于”类实例,而成员变量“属于”类实例。我们所说的“类实例”概念,指的是一块内存区域,包含了isa指针和所有的成员变量。所以假如允许动态修改类成员变量布局,已经创建出的类实例就不符合类定义了,变成了无效对象。但方法定义是在objc_class中管理的,不管如何增删类方法,都不影响类实例的内存布局,已经创建出的类实例仍然可正常使用。