一、类目的简单介绍
1.什么是类目(类别)
类别( category )是 Objective-C 语言的新特性,为现有的类添加新方法的方式。比如系统的类,我们看不到他的.m文件,所以没有办法用直接添加方法的方式去实现,用类目就可以实现在没有类的源代码的条件下为类增加新的方法。
通过类目加入的方法会成为原始类的一部分。例如:通过类目想NSString增加方法,编译器会把这些方法加到NSString的定义里;类目里定义的方法可以干任何原始类中方法能干的事,在运行时他们是平等对待的;类目里定义的方法也会被原始类的子类所继承,就跟原始类的其他方法一样。
2.类目的局限性
a、无法添加新的实例变量。
b、若在类目中覆盖现有类的原有方法。这样会引起super消息的断裂,因为类目总的方法具有更高的优先级,因此,一般不要覆盖现有类中的方法
3.类目的声明结构
@interface 要加类目的类名A(类目名B)
//声明类目添加的方法
@end
二、类目的添加方法功能
我们下面举一个为系统的类NSString通过类目添加方法的例子
1.首先建立一个项目,添加一个主页MainViewController类,然后为NSString类添加一个类目类NSString+Category
过程:new file->Source->Objective-C File->next
File Type 可以选取类目延展或者协议 File处填写类目名
之后就会生成NSString+Category的.h和.m文件,之后就可以为NSString类添加方法了,下面直接上代码来说明
在NSString+Category.h中
#import <Foundation/Foundation.h>
//前面是要加方法的类名,后面括号内为类目名,该类目中的方法可被NSString的对象调用
@interface NSString (Category)
-(NSNumber *)lengthASNumber;
@end
在NSString+Category.m中
#import "NSString+Category.h"
@implementation NSString (Category)
-(NSNumber *)lengthASNumber
{ //self为调用该方法的对象,自己调用自己的方法
int length=(int)[self length];
NSNumber *n=[NSNumber numberWithInt:length];
return n;
}
@end
在MainViewController中导入NSString+Category.h后可直接通过NSString调用-(NSNumber *)lengthASNumber方法,例子
NSString *s1=@"one";
//用类目方法实现,该方法属于NSString
NSNumber *n1=[s1 lengthASNumber];
三、类目的拆分功能
其实类目有一个非常重要的功能,就是实现类的方法的拆分(避免一个类中写入方法太多,代码冗余,还可以将同类的方法写入同一个地方,比较合理),下面通过代码来实现类目的拆分功能
同样建一个项目,有一个主页类MainViewController,另外建立一个自己的类MyClass,并为MyClass建立两个类目MyClass+Category1和MyClass+Category2,这里注意,需要把这两个类目的头文件都删除掉,然后将两个类目的声明放在MyClass.h中,MyClass.h代码如下
#import <Foundation/Foundation.h>
@interface MyClass : NSObject
{
int va1;
int va2;
int va3;
}
-(void)setVa1:(int)ava1;
-(int)va1;
@end
//MyClass +Category1头文件中的内容
@interface MyClass (Category1)
//记得,这里的方法和MyClass自己本身的方法是同一级别的
-(void)setVa2:(int)ava2;//赋值
-(int)va2;//返回
@end
//MyClass +Category2头文件中的内容
@interface MyClass (Category2)
-(void)setVa3:(int)ava3;
-(int)va3;
@end
在MyClass+Category1.m和MyClass+Category2.m中的代码如下
//这里有个小细节,将MyClass+Category1.h改为MyClass.h
#import "MyClass.h"
@implementation MyClass (Category1)
-(void)setVa2:(int)ava2
{
va2=ava2;
}
-(int)va2
{
return va2;
}
@end
//将MyClass+Category2.h改为MyClass.h
#import "MyClass.h"
@implementation MyClass (Category2)
-(void)setVa3:(int)ava3
{
va3=ava3;
}
-(int)va3
{
return va3;
}
@end
然后,在MyClass.m中的代码是这样的
#import "MyClass.h"
@implementation MyClass
-(NSString *)description
{
return [NSString stringWithFormat:@"%d %d %d",va1,va2,va3];
}
-(void)setVa1:(int)ava1
{
va1=ava1;
}
-(int)va1
{
return va1;
}
@end
最后,就可以在MainViewController中直接导入MyClass.h然后调用其本身和其类目中的方法了(注意:两个类目中可以添加不相同类型的方法,实现同种方法放在一起,这里就不再详细实现了)
MyClass *m=[[MyClass alloc]init];
[m setVa1:1];
[m setVa2:2];
[m setVa3:3];
NSLog(@"%@",m);
至此,类目的介绍基本完成。
四、说说类目与继承的区别
使用类目无需生成子类,可以直接为现有类添加方法,继承则需要生成子类来实现添加方法;子类可以重写父类方法,同时可以继承调用父类的实现,但是类目扩展的方法如果与现有类的方法重名,会覆盖原类的实现,无法访问到原来的方法;子类可以为父类扩展属性和成员变量,这一点类目无法实现。