0x01 什么是依赖关系
依赖关系是两个实体之间的一种关系。
依赖关系可以存在于两个类之间,也可以存在于两个或多个文件之间。两者之间任何一个发生变化,都需要重新编译相关的文件来适应变化。
导入头文件使头文件和源文件之间建立了依赖关系。由于依赖关系是传递的,头文件之间也可能互相依赖,所以如果某个头文件发生变化,可能一系列的文件都将需要重新编译,这将使编译时间大大加长,影响编译效率。
0x02 依赖关系导致负面影响的原因
导致依赖关系问题的原因是Objective-C编译器需要知道某些信息才能工作。
有时候编译器需要知道类的全部信息,例如它的实例变量配置、它所继承的所有类等,而有的时候,编译器只需要知道类名即可,不需要了解整个定义。
0x03 减少依赖关系负面影响的方法
Objective-C提供了一个方法, 能够减少由依赖关系引起的重新编译带来的负面影响。
Objective-C引入了关键字@class来告诉编译器:“这是一个类,所以我只会通过指针来引用它。”这样编译器就不必知道关于这个类的更多信息,只要了解它是通过指针来引用的即可。
仔细观察此前帖子中的Car类接口,我们可以看到它通过指针引用了Tire和Engine,所以这里可以用@class代替#import语句:
#import <Cocoa/Cocoa.h>
@class Tire;
@class Engine;
@interface Car : NSObject
- (void) setEngine: (Engine *) newEngine;
- (Engine *) engine;
- (void) setTire: (Tire *) tire
atIndex: (int) index;
- (Tire *) tireAtIndex: (int) index;
- (void) print;
@end // Car
@class创建了一个前向引用。
如果有循环依赖关系,即A类使用B类,B类使用A类,此时通过#import语句让这两个类互相引用,将会出现编译错误。而在A类中使用@class B,在B类中使用@class A,如此互相引用是可以的。
0x04 导入和继承
回顾之前我们创建的Slant6类和AllWeatherRadial类,分别继承自Engine类和Tire类。
由于它们是继承自其它类而不是通过指针指向其它类的,所以在头文件里不能使用@class语句。
因为编译器需要先知道所有关于超类的信息才能成功地为其子类编译@interface部分。
所以Slant6.h仍然如下所示:
#import "Engine.h"
@interface Slant6 : Engine
@end // Slant6
Slant6.h中没有#import <Cocoa/Cocoa.h>,因为在其超类Engine.h中已经导入过了。
但是在该文件里加上#import <Cocoa/Cocoa.h>也没有问题,因为#import命令不会重复导入已经被导入的文件。