1、将引入头文件的时机尽量延后,只在确有需要时才引入,这样就可以减少类的使用者所需引入的头文件数量。
2、如果类 EOCEmployer 中 import 了 EOCPerson,而 EOCPerson 中也 import 了 EOCEmployer ,此时,若要编译EOCEmployer,则编译器必须知道EOCPerson这个类,而要编译EOCPerson,则又必须知道EOCEmployer。如果在各自头文件中引入对方的头文件,则会导致“循环引用”(chicken-and-egg situation)。当解析其中一个头文件时,编译器会发现它引入了另一个头文件,而那个头文件又回过头来引用第一个头文件。使用 #import 而非 #include 指令虽然不会导致死循环,但却这意味着两个类里有一个无法被正确编译。如果不信的话,读者可以自己试试。
3、但是有时候必须要在头文件中引入其他头文件。如果你写的类继承自某个超类,则必须引入定义那个超类的头文件。同理,如果要声明你写的类遵从某个协议(protocol),那么该协议必须有完整定义,且不能使用向前声明。向前声明只能告诉编译器有某个协议,而此时编译器却要知道该协议中定义的方法。
例如,要从图形类中继承一个矩形类,且令其遵循绘制协议:
// EOCRectangle.h
#import “EOCShape.h”
#import “EOCDrawable.h”
@interface EOCRectangle : EOCSharpe <EOCDrawable>
@property (nonatomic, assign) float width;
@property (nonatomic, assign) float height;
第二条 #import 是难免的。鉴于此,最好是把协议单独放在一个头文件中。要是把 EOCDrawable 协议放在了某个大的头文件里,那么只要引入此协议,就必定会引入那个头文件中的全部内容,如此一来,就像上面说的那样,会产生相互依赖问题,而且还会增加编译时间。
然而,有些协议如委托协议,就不用单独写一个头文件了。
每次在头文件中引入其他头文件之前,都要先问问自己这样做是否确有必要。如果可以用向前声明取代引入,那么就不要引入。若因为要实现属性、实例变量或者要遵循协议而必须引入头文件,则应尽量将其移至“class-continuation分类”中。
要点
① 除非确有必要,否则不要引入头文件。一般来说,应在某个类的头文件中使用向前声明来提及别的类,并在实现文件中引入那些类的头文件。这样做可以尽量降低类之间的耦合。
② 有时无法使用向前声明,比如要声明某个类遵循一项协议。在这种情况下,尽量把“该类遵循某协议”的这条声明移至“class-continuation分类”中。如果不行的话,就把协议单独放在一个头文件中,然后将其引入。