将程序拆分为多个小文件有助于更快地找到重要的代码,而且其他人在查看项目时也能有个大致的了解。
拆分接口和实现
根据@interface
和@implementation
,OC的代码通常放在两种文件里:
- 接口部分(.h):类的@interface指令、公共struct定义、enum常量、#defines和extern全局变量等。
- 实现部分(.m): 类的@implementation指令、全局变量的定义、私有struct等。
另外,复杂的项目可以拥有多个目标,它们源文件的配置各不相同,构建规则也不同。群组关系仅仅是有Xcode负责管理的一项奇妙的功能。
拆分Car程序
#import
带尖号的是导入系统头文件(只读),如#import <Foundation/Foundation.h>
;双引号是项目本地的代码文件,如#import "Engine.h"
。- 拆分上一篇中的Car程序
首先拆分继承自NSObject
的类:Tire
和Engine
。
1 | // Tire.h |
1 | // Tire.m |
1 | // Engine.h |
1 | // Engine.m |
使用跨文件依赖关系
@class
是告诉编译器:“这是一个类,只会通过指针来引用它,不需要关注此类的更多信息”。可减少必须导入的头文件的数量,从而缩短编译时间。
拆分Car
类:1
2
3
4
5
6
7
8
9
10
11
12
13
14// Car.h
#import <Foundation/Foundation.h>
@class Engine;
@class Tire;
@interface Car : NSObject
- (Engine *) engine;
- (void) setEngine: (Engine *) newEngine;
- (Tire *) tireAtIndex: (int) index;
- (void) setTire: (Tire *) tire atIndex: (int) index;
- (void)print;
@end //Car1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57// Car.m
#import "Car.h"
#import "Tire.h"
#import "Engine.h"
@implementation Car
{
Engine *engine;
Tire *tires[4];
}
- (Engine *) engine
{
return (engine);
} //engine
- (void) setEngine:(Engine *)newEngine
{
engine = newEngine;
} //setEngine
- (void) setTire:(Tire *)tire atIndex:(int)index
{
if (index<0 || index>3) {
NSLog(@"bad index (%d) in setTire:atIndex", index);
exit(1);
}
tires[index] = tire;
} // setTire
- (Tire *) tireAtIndex:(int)index
{
if (index<0 || index>3) {
NSLog(@"bad index (%d) in setTire:atIndex", index);
exit(1);
}
return tires[index];
} // tireAtIndex
- (id)init
{
if (self = [super init]) { //?
engine = [Engine new];
tires[0] = [Tire new];
tires[1] = [Tire new];
tires[2] = [Tire new];
tires[3] = [Tire new];
}
return (self);
}
- (void)print
{
NSLog(@"%@", engine);
NSLog(@"%@", tires[0]);
NSLog(@"%@", tires[1]);
NSLog(@"%@", tires[2]);
NSLog(@"%@", tires[3]);
}
@end //Car编译器需要先知道所有关于超类的信息才能成功地为其子类编译@interface部分。
拆分Slant6
和AllWeatherRadial
:1
2
3
4
5
6
7// Slant6.h
#import "Engine.h"
@interface Slant6 : Engine
@end1
2
3
4
5
6
7
8
9// Slant6.m
#import "Slant6.h"
@implementation Slant6
- (NSString *)description {
return (@"I am a slant-6.VROOM!");
}
@end1
2
3
4
5
6
7// AllWeatherRadial.h
#import "Tire.h"
@interface AllWeatherRadial : Tire
@end1
2
3
4
5
6
7
8
9
10// AllWeatherRadial.m
#import "AllWeatherRadial.h"
@implementation AllWeatherRadial
-(NSString *)description
{
return (@"I am a tire for rain or shine.");
}
@end
最后是main.m
文件:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24// main.m
#import <Foundation/Foundation.h>
#import "Car.h"
#import "Tire.h"
#import "Engine.h"
#import "Slant6.h"
#import "AllWeatherRadial.h"
int main(int argc, const char * argv[]) {
Car *car = [Car new];
Engine *engine = [Slant6 new];
[car setEngine:engine];
for (int i=0; i<4; i++) {
Tire *tire = [AllWeatherRadial new];
[car setTire:tire atIndex:i];
}
[car print];
return 0;
}