类别介绍:
在OC中没有抽象类的语法支持,为了达到这个目的,使用类别来实现。类别(category),oc的动态特征允许使用类别为现有的类添加新方法,并不需要创建子类,不需要访问原有类的源代码。
Category定义格式如下:
@interface 已有类(类别名)
,,,方法定义
@end
类别的实现部分:
@implementation 已有类别(类别名)
//方法实现
@end
类别的命名:类名+类别名.h;实现部分定义为:类名+类别名.m
NSNumber+lwb.h文件如下:
#import <Foundation/Foundation.h>
@interface NSNumber (lwb)
-(NSNumber*) add:(double)num2;
-(NSNumber*) substract:(double)num2;
-(NSNumber*) multiply:(double)num2;
-(NSNumber*) divide:(double)num2;
@end
#import "NSNumber+lwb.h"
@implementation NSNumber (lwb)
-(NSNumber*) add:(double) num2 {
return [NSNumber numberWithDouble:([self doubleValue]+num2)];
}
-(NSNumber*) substract:(double) num2 {
return [NSNumber numberWithDouble:([self doubleValue]-num2)];
}
-(NSNumber*) multiply:(double) num2 {
return [NSNumber numberWithDouble:([self doubleValue]*num2)];
}
-(NSNumber*) divide:(double) num2 {
return [NSNumber numberWithDouble:([self doubleValue]/num2)];
}
@end
测试文件如下:
#import "NSNumber+lwb.h"
int main(int argc, const char * argv[]) {
NSNumber* number=[[NSNumber alloc]initWithDouble:10.0];
NSLog(@"the add result==%g",[[number add:10.0] doubleValue]);
NSLog(@"the substract==%g",[[number substract:9.0] doubleValue]);
NSLog(@"the multiply==%g",[[number multiply:2.0]doubleValue]);
NSLog(@"the divide==%@",[number divide:2.0]);
return 0;
}
通过类别,很容易去重写源文件中的已有的函数,但通常 不推介这么做,如果需要重写原有的类的方法,更好的建议是通过原有类派生子类,然后在子类中重写弗雷原有的方法。
注意:
1、通过类别为指定类添加新方法之后,这个新方法不仅会影响NSNumber类,而且还会影响NSNumber类的所有子类。每个子类将获取类别扩展的方法。
2、可以根据需要为一个类定义多个类别,不同的类别都可对原有的类增加方法定义。
利用类别对类进行模块儿化设计
考虑到如果一个类非常大的时候,如果把所有的方法都写在一个*.m文件中,那么这个文件会变得非常的大,而且难于管理;如果可以将这个大的文件分别分布到不同的小的文件中,那么可以有效的对代码进行管理。这个时候,利用类别进行分类管理有效的解决这一问题。
如:
@interface NSWindow (NSKeybordUI);
@interface NSWindow (NSToolbarSupport);
@interface NSWindow (NSDrag);
这样,就将NSWindow中的方法分散到了不同的文件中。
利用类别来调用私有方法
在OC中并没有真正的私有方法,如果使用NSObject的performSelector:方法来执行动态调用,完全可以调用那些私有方法。虽然说如果一个方法并没有在接口部分去定义,而是在类的实现部分提供实现的方法被称为私有方法,通常不允许直接去调用。使用performSelector:来执行调用可以避开编译器的语法检查,从而调用私有方法;除此之外,可以使用类别来定义前向引用,从而实现对私有方法的调用。
利用类别对私有方法进行调用如下:
LWBItem.h文件内容如下:
#import <Foundation/Foundation.h>
@interface LWBItem : NSObject
@property (nonatomic,assign) double price;
-(void) info;
@end
LWBItem.m文件内容如下:
#import "LWBItem.h"
@implementation LWBItem
@synthesize price;
-(void) info {
NSLog(@"This is a usual func");
}
-(double) calDiscount:(double) discount{
return self.price*discount;
}
@end
我们在源文件中增加了calDiscount私有方法;
LWBItem (discount).h 文件内容如下:
#import <Foundation/Foundation.h>
#import "LWBItem.h"
@interface LWBItem (discount)
-(double) calDiscount:(double) discount;
@end
这样,利用类别我们可以在测试文件中调用LWBItem的私有方法calDiscount方法来进行执行。
说白了就像C语言中的函数申明于定义分开写,如果没有头文件当然是访问不到对应的函数的,所以在此就类似于重新申明函数原型和其对应起来。不过这个是面向对象的,嵌入以后对其子类有所影响(正如上面所说的)。
扩展
扩展与类别类似,扩展相当于匿名类别,其语法格式如下:
@interface 已存在的类 ()
{
//实例变量
}
//方法定义
...
@end
类别通常有*.h和*.m文件,.m文件会为特定的类别提供实现;而对于扩展来说,起只有.h文件,扩展的实现仍然写在原类的.m文件中。
注意:在定义类的扩展时,可以额外增加实例变量,也可以使用@property、@synthesize来合成setter和getter方法,但定义类别时,则不允许额外定义实例变量。
利用扩展进行类的扩展代码如下:
LWBCar.h文件如下:
#import <Foundation/Foundation.h>
@interface LWBCar : NSObject
@property(nonatomic,copy) NSString* brand;
@property(nonatomic,copy) NSString* model;
-(void) drive;
@end
LWBCar+drive.h文件内容如下:
#import "LWBCar.h"
#ifndef LWBCar_drive_h
#define LWBCar_drive_h
@interface LWBCar ()
@property (nonatomic,copy)NSString* color;
-(void)drive:(NSString*)owner;
@end
#endif /* LWBCar_drive_h */
#import "LWBCar+drive.h"
@implementation LWBCar
@synthesize brand=_brand;
@synthesize model=_model;
@synthesize color=_color;
-(void) drive {
NSLog(@"%@汽车正在路上奔驰",self);
}
// this is a drive method
-(void)drive:(NSString*) owner{
NSLog(@"%@正在驾驶%@汽车在路上奔驰",owner,self);
}
-(NSString*)description{
return [NSString stringWithFormat:@"[barnd=%@,model=%@,color=%@]",self.brand,self.model,self.color];
}
-(LWBCar*) init{
self.brand=@"宝马";
self.model=@"x60";
self.color=@"红色";
return self;
}
@end
在测试文件中,我们不仅可以调用源文件和扩展文件中定义的成员变量和方法。