分类是什么?
分类也是Objective-C的一项重要语言特性。利用分类机制,我们无须继承子类即可直接为当前类添加方法,而在其他编程语言中,则需要通过继承子类来实现。由于Objective-C运行期系统是高度动态的,所以才支持这一特性。
为什么要将实现代码分散到分类中?
类中经常容易填满各种方法,而这些方法的代码则全部堆在一个巨大的实现文件里。有时这么做是合理的,因为即便通过重构把这个类打散,效果也不会更好。在此种情况下,可以通过Objective-C的分类机制,把类代码按逻辑划入几个分区中,这对开发和调试都有好处。
通过分类机制,可以把类代码分成很多个易于管理的小块,以便单独检视。
即使类本身不是太大,我们也可以使用分类机制将其切割成几块,把相应代码归入不同的功能区中。cocoa中的NSURLRequest类及其可变版本NSMutableURLRequest类就是这么做的。这个类用于执行从URL中获取数据的请求,而且通常使用HTTP协议从因特网中的某个服务器上获取数据。
为了扩展NSURLRequest类,把与HTTP有关的方法归入名为NSHTTPURLRequest的分类中,而把与可变版本有关的方法归入名为NSMutableHTTPRequest的分类中。与HTTP有关的方法却又要单独放在一起,因为若是不这么做的话,该类的使用者就会有疑问:为什么能在使用FTP协议的request对象上设置"HTTP方法"呢?
之所以要将类代码打散到分类中还有个原因,就是便于调试:对于某个分类中的所有方法来说,分类名称都会出现在其符号中。例如,"addFriend:"方法的"符号名"如下:
-[EOCPerson(Friendship) addFriend:]
在调试器的回溯信息中,会看到类似下面这样的内容:
frame #2: 0x00001c50 Test '- [EOCPerson(Friendship) addFriend:]
+ 32 at main.m:46
根据回溯信息中的分类名称,很容易就能精确定位到类中的方法所属的功能区,这对于某些应该视为私有的方法来说更是极为有用。可以创建名为Private的分类,把这种方法全部放在里面。
分类如何实现?
分类有两种实现方式,一种是直接把整个类都定义在一个接口文件中,并将其代码写在一个实现文件中。
也可以把不同的分类拆分成几个不同的文件。以EOCPerson为例,可以按照其分类拆分以下几个文件:
- EOCPerson + Friendship(.h/.m)
- EOCPerson + Work(.h/.m)
- EOCPerson + Play(.h/.m)
比方说,与交友功能相关的那个分类可以这样些:
//EOCPerson + Friendship.h
#import "EOCPerson.h"
@interface EOCPerson (Friendship)
-(void)addFriend:(EOCPerson*)person;
-(void)removeFriend:(EOCPerson *)person;
-(void)isFriendsWith:(EOCPerson *)person;
@end
//EOCPerson + Friendship.m
#import "EOCPerson + Friendship.h"
@implementation EOCPerson (Friendship)
-(void)addFriend:(EOCPerson *)person
{
}
-(void)removeFriend:(EOCPerson *)person
{
}
-(void)isFriendsWith:(EOCPerson *)person
{
}
@end