分类、继承、类别
(一)category
category的主要作用是为已经存在的类添加方法
可以把类的实现分开在几个不同的文件里面
• 可以减少单个文件的体积
• 可以把不同的功能组织到不同的category里
• 可以由多个开发者共同完成一个类
• 可以按需加载想要的category
声明私有方法
category的其他几个使用场景:
• 模拟多继承(另外可以模拟多继承的还有protocol)
• 把framework的私有方法公开
category特点
• category只能给某个已有的类扩充方法,不能扩充成员变量。
• category中也可以添加属性,只不过@property只会生成setter和getter的声明,不会生成setter和getter的实现以及成员变量,需要使用runtime 来实现。
• 如果category中的方法和类中原有方法同名,运行时会优先调用category中的方法。也就是,category中的方法会覆盖掉类中原有的方法。所以开发中尽量保证不要让分类中的方法和原有类中的方法名相同。避免出现这种情况的解决方案是给分类的方法名统一添加前缀。比如category_。
• 如果多个category中存在同名的方法,运行时到底调用哪个方法由编译器决定,最后一个参与编译的方法会被调用。
调用优先级
• 分类(category) > 本类 > 父类。即,优先调用cateory中的方法,然后调用本类方法,最后调用父类方法。
注意:category是在运行时加载的,不是在编译时。
为什么category不能添加成员变量?
因为在运行期,对象的内存布局已经确定,如果添加实例变量就会破坏类的内部布局,这对编译型语言来说是灾难性的
Objective-C类是由Class类型来表示的,它实际上是一个指向objc_class结构体的指针,
在Runtime中,objc_class结构体大小是固定的,不可能往这个结构体中添加数据,只能修改
需要注意的有两点:
• 1)、category的方法没有“完全替换掉”原来类已经有的方法,也就是说如果category和原来类都有methodA,那么category附加完成之后,类的方法列表里会有两个methodA。
• 2)、category的方法被放到了新方法列表的前面,而原来类的方法被放到了新方法列表的后面,这也就是我们平常所说的category的方法会“覆盖”掉原来类的同名方法,这是因为运行时在查找方法的时候是顺着方法列表的顺序查找的,它只要一找到对应名字的方法,就会罢休,殊不知后面可能还有一样名字的方法。
修改
(二)Extension
extension被开发者称之为扩展、延展、匿名分类。extension看起来很像一个匿名的category,但是extension和category几乎完全是两个东西。和category不同的是extension不但可以声明方法,还可以声明属性、成员变量。extension一般用于声明私有方法,私有属性,私有成员变量。
注意:extension常用的形式并不是以一个单独的.h文件存在,而是寄生在类的.m文件中。
category和extension的区别
就category和extension的区别来看,我们可以推导出一个明显的事实,extension可以添加实例变量,而category是无法添加实例变量的(因为在运行期,对象的内存布局已经确定,如果添加实例变量就会破坏类的内部布局,这对编译型语言来说是灾难性的)。
• extension在编译期决议,它就是类的一部分,但是category则完全不一样,它是在运行期决议的。extension在编译期和头文件里的@interface以及实现文件里的@implement一起形成一个完整的类,它、extension伴随类的产生而产生,亦随之一起消亡。
• extension一般用来隐藏类的私有信息,你必须有一个类的源码才能为一个类添加extension,所以你无法为系统的类比如NSString添加extension,除非创建子类再添加extension。而category不需要有类的源码,我们可以给系统提供的类添加category。
• extension可以添加实例变量,而category不可以。
• extension和category都可以添加属性,但是category的属性不能生成成员变量和getter、setter方法的实现。
(三)继承
适用继承的场合
- 父类只是给子类提供服务,并不涉及子类的业务逻辑
- 层级关系明显,功能划分清晰,父类和子类各做各的。
- 父类的所有变化,都需要在子类中体现,也就是说此时耦合已经成为需求
4.在我看来一个很重要的原则就是我们不能脱离cocoa框架开发,所以我们可以继承cocoa的类,以达到快速开发的目的,但是如果没有特殊原因我们写的代码要控制在继承链不增加两层。