1.分类
使用Object-C中的分类,是一种编译时的手段,允许我们通过给一个类添加方法来扩充它(但是通过category不能添加新的实例变量),并且我们不需要访问类中的代码就可以做到。
我们可以为一个类创建一个新的方法,而不需要在代码中编辑类定义。它提供了扩展类定义的便捷的方式,并且不必访问类的源代码,也无需创建子类。
#import <Foundation/Foundation.h>
@interface Fraction : NSObject
@property int numerator,denominator;
-(void) print;
-(void) setTo:(double) n over:(double)d ;
-(double) converToNum;
-(void) reduce;
@end
现在想要向Fraction类添加加减乘除四个方法,则新的分类Mathops的接口部分代码如下:#import "Fraction.h"
@interface Fraction (MathOps) //告诉编译器正在为Fraction 类定义新的分类,它的名字为MathOps。
-(Fraction*) add: (Fraction*)f;
-(Fraction*) subtract: (Fraction*) f;
-(Fraction*) multiply: (Fraction*) f;
-(Fraction*) divide: (Fraction*) f;
@end
这既是接口部分的定义,也是现有接口部分的扩展。因此,必须必须包括原有的接口部分。这部分方法声明可以放在主类文件中,此时不需要#import "Fraction.h"。也可以单独放在一个文件中,此时需要在主类的接口文件文件中声明实例变量。category的几个典型的应用场景:
1。对框架提供类的扩展(没有源码,不能修改)。
2。 不想生成一个新的子类的情况下,比如对 NSArray 的扩展。
3。 方便做项目管理,可以将一份源码在多个地方共享或者做方法版本管理、多人协作开发、用本地版本替换公共版本实现。
不建议在 category 中覆盖类中的方法,因为在 category 中的方法不能调用 superClass 的方法(因为没有元数据支持)
category 方法不能覆盖于同一class 的其它 category 中的方法。因为不法预知他们的加载优先顺序,就可能在编译时出错。
对类库的 category 方法覆盖对导致整个类库的行为发生变化,因此调用那些方法的类不知道方法的实现已经发生了变化。
警告:
虽然 category 不限于任何 class ,但是仍然不建议编写针对 rootClass 的 category. 原因是影响面较大,其它开发人员如果不注意的话就会出问题。
而且类对象也可能调用这些方法,甚至在调用时的 self 指针不是实例而是类对象本身。
注意事项:
1.分类可以覆盖该类中的另一个方法,但通常不提倡这种做法。当覆盖了一个方法之后就不可以访问原来的方法,因此,必须将被覆盖中的方法中的所有代码复制到替换它的方法中。如果确实需要覆写方法,可以通过创建子类来实现,这样仍然可以通过super来访问父类的的方法,就可以不必了解被覆写的方法的复杂内容,就能够调用父类的方法,并向子类添加新方法。
2,如果同一个方法在多个分类中都定义,调用时不会指定调用哪一个。
3.通过使用分类添加新方法来扩展类不仅会影响这个类,而且影响他的所有子类。例如,如果NSObject添加新方法,对于每个NSObject的子类,都会继承这些新方法。
4.通过分类为现有类添加新方法可能对你有用,但他们有可能和该类的原始设计或意图不一致。例如:通过添加一些新分类和方法来修改Square类的定义,将Square变成Circle。
5.对象/分类命名必须是唯一的。也就是蕾丝这样的@interface NSString (Utilities),因为在objective c的命名空间中,只能存在一个NSString 的分类。