第24条 将类的实现代码分散到便于管理的数个分类之中

2017/8/31 posted in  第四章 协议与分类

一个类里面经常会填满各种各样的方法,有时候将那么多方法放在一个类的实现文件里是合理的。但是我们如果通过OC的分类机制将类代码按逻辑划入几个分区中,这对于开发和调试都有帮助。

我们来举个例子,我们对个人信息建模分类:

#import <Foundation/Foundation.h>
Sinterface EOCPerson : NSObject
@property (nonatomic, copy, readonly) NSString *firstName; 
@property (nonatomic, copy, readonly) NSString *lastName; 
@property (nonatomic, strong, readonly) NSArray *friends;

-(id)initWithFirstName:(NSString*) firstName
            andLastName:(NSString*)lastName;
            
/* Friendship methods */
-(void)addFriend:(EOCPerson*)person;
- (void)removeFriend:(EOCPerson*)person;
-(BOOL)isFriendsWith:(EOCPerson*)person;

/* Work methods */
-(void)performDaysWork;
-(void)takeVacationFromWork;

/* Play methods */
-(void)goToTheCinema;
-(void)goToSportsGame;

在实现该类时,所有方法的代码可能会写在一个大文件里。显得很臃肿。所以可以用“分类”机制把刚才的类改写成下面这样:

@import <Foundation/Foundation.h>
@interface EOCPerson : NSObject
@property (nonatomic, strong, readonly) NSArray *friends;
@property (nonatomic, copy, readonly) NSString *lastName;
@property (nonatomic, copy, readonly) NSString *firstName; 
 
-(id) initWithFirstName: (NSString*)firstName
            andLastNames:(NSString*)lastName;

@end

@interface EOCPerson (Friendship)
-(void)addFriend:(EOCPerson*)person;
-(void)removeFriend:(EOCPerson*)person;
-(BOOL)isFriendsWith:(EOCPerson*)person; 
@end

@interface EOCPerson (Work)
-(void)performDaysWork;
-(void)takeVacationFromWork; 
@end

@interface EOCPerson (Play)
-(void)goToTheCinema;
-(void)goToSportsGame;
@end

现在,类的实现代码按照方法分成了好几个部分。所以说,这项语言特性当然就叫做“分类”啦。

但是这些代码还是在一个文件中声明的,所以我们还可以将其拆分为多个文件:

  • 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;
-(BOOL)isFriendsWith:(EOCPerson*)person;
@end

// EOCPerson+Friendship.m 

#import EOCPerson+Friendship.h
@implementation EOCPerson (Friendship)
-(void)addFriend:(EOCPerson*)person {
    /*...*/
}
-(void)removeFriend:(EOCPerson*)person {
    /*...*/
}
-(BOOL)isFriendsWith:(EOCPerson*)person {
    /*...*/
}
@end

通过分类机制,可以把类代码分成很多个易于管理的小块,以便单独检视。使用分类机制之后,如果想用分类中的方法,那么要记得在引入EOCPerson.h时一并引入分类的头文件

这样使用分类之后,对于某个分类中的所有 方法来说,分类名称都会出现在其符号中。例如,“addFriend:”方法的“符号名”(symbol name)如下:

-[EOCPerson(Friendship) addFriend:]

也可以创建名为Private的分类把这种方法全都放在里面。这个分类里的方法一般只会在类或框架内部使用,而无须对外公布。这样一来,类的使用者有时可能会在査看回溯信息时发现private一词,就知道不应该直接调用此方法了。

要点

  • 使用分类机制把类的实现代码划分成易于管理的小块。
  • 将应该视为“私有”的方法归入名叫Private的分类中,以隐藏实现细节。