分类本身是一个类,附属与另一个类,分类对其附属的类进行扩展(不必访问其附属类的源代码),扩展类的定义(一般是方法 method)。
2.分类与子类的差异是什么,两者有何关系?
分类是对其附属类的扩展,所以要在分类的接口(interface...)前使用 #import 来包含其附属类的接口文件,分类自身并不含有其附属类的一些实例变量和方法。子类则是对其父类的继承,并能够进行扩展,定义更多的方法和实例变量。
假设现在有三个类,分别为A,B,C。C为A的子类,B为A的分类。由于A,B之间是一种附属关系,所以B的定义会对A的子类C产生影响。通过使用分类添加新方法来扩展类,不仅会影响这个类,同时也会影响它的所有子类。每个子类都将继承这些新方法。
3.如何定义分类?
#import<Foundation/Foundation.h>
/* 定义 Fraction类 */
@interface Fraction: NSObject
@property int numerator, denominator;
-(void) setTo: (int) n over: (int) d;
-(Fraction *) add: (Fraction *) f;
-(void) reduce;
-(double) convertToNum;
-(void) print;
@end
/* 从接口部分删除add: 方法,并将其添加到新分类中,同时添加其它三种要实现的数学运算。新的 MathOps 分类的接口部分代码如下:*/
#import<Foundation>
@interface Fraction (MathOps)
-(Fraction *) add: (Fraction *) f;
-(Fraction *) mul: (Fraction *) f;
-(Fraction *) sub: (Fraction *) f;
-(Fraction *) div: (Fraction *) f;
@end
/* 以上既是接口部分的定义,也是现有接口部分的扩展。所以要包含原始接口部分。*/
/* 在该分类的实现部分,我们应该这么写
@implementation Fraction (MathOps)
…
…
…
*/
创建一个未命名的分类,且在括号“()”之间不指定名字,这是一种特殊的情形。这种特殊的语法定义为类的扩展。在我们定义一个像这样的未命名分类时,可以通过定义附加的实例变量来扩展类,这在命名的分类中是不允许的。未命名分类中,声明的方法需要在主实现区域实现,而不是在分离的实现区域中实现。如果没有实现未命名分类的接口部分列出的全部方法,编译器会发出警告。
例如:
#import"GraphicObject.h"
/* 类的扩展 */
@interface GraphicObject()
@property int uniqueID;
-(void) doStuffWithUniqueID: (int) theID;
...
...
@end
@implementation GraphicObject
@synthesize uniqueID;
-(void) doStuffWithUniqueID: (int) theID
{
self.uniqueID = theID;
...
...
}
/* 其它的 GraphicObject 方法的实现 */
@end