Effective Objective-C2.0 笔记(二)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_28285625/article/details/88978390

在类的头文件中尽量少引用其他头文件

与C和C++一样,Objective-C也使用“头文件”(header file)与“实现文件”(implement file)来区隔代码。
如果AAA类的每个实例都应该有一个BBB,于是直接为其添加一项属性

@property (nonatomic,strong) BBB *b;

然而这么做有个问题,就是在编译引入AAA.h文件时,BBB类并不可见,不便强迫开发者在引入AAA.h时必须引入BBB.h,所以,常见的办法是在AAA.h文件中加入下面这行:
#import "BBB.h"
这种办法可行,但是不够优雅。在编译一个使用了AAA类的文件时,不需要知道BBB类的全部细节,只需要知道有一个类名叫BBB就好。所幸有个办法能把这一情况告诉编译器:
@class BBB;
这叫做“向前声明”(forward declaring)该类。
AAA类的实现文件则需要引入BBB类的头文件,因为若要使用后者,则必须知道其所有接口细节。于是在AAA.m文件中导入BBB类的头文件。

#import "AAA.h"

将引入头文件的时机尽量延后,只在确有需要的时候引入,这样就可以减少类的使用者所需引入的头文件数量。假设BBB.h引入到AAA.h,那么只要引入AAA.h文件就会一并引入BBB.h所有内容。此过程若持续下去,则要引入许多根本用不到的内容,这当然会增加编译时间。
向前声明也解决了两个类相互引用的问题。
但是有时候必须要在头文件中引入其他头文件。如果你写的类继承自某个超类,则必须引入定义那个超类的头文件。同理,如果要声明你写的类遵从某个协议(protpcol),那么该协议必须有完整定义,且不能使用向前声明。向前声明只能告诉编译器有某个协议,而该编译器却要知道该协议中定义的方法。
例如,要从图形类中继承一个矩形类,且令其遵循绘制协议,#import是难免的,鉴于此,最好是把协议单独放在一个头文件中,要是把协议放在了某个大的头文件中,那么只要引入此协议,就必定会引入那个头文件中的全部内容,如此一来,就像上面说的那样,会产生相互依赖问题,而且还会增加编译时间。
然而有些协议,例如“委托协议”(delegate protocol,参见第23条),就不用单独写一个头文件了。在那种情况下,协议只有与接受协议委托的类放在一起定义才有意义。此时最好能在实现文件中声明此类实现了该委托协议(意思就是在.m文件中声明),并把这段实现代码放在“class-continuation分类”(class-contunuation category,参见第27条)里。这样做不仅可以缩减编译时间,而且还能降低彼此依赖程度。若是依赖关系过于复杂,则会给维护带来麻烦,而且,如果只想把代码的某个部分开放为公共API的话,太复杂的依赖关系也会出问题。

要点

  • 除非有必须要,否则不要引入头文件。一般来说,应在某个类的头文件中使用向前声明来提及别的类,并在类的.m文件中引入那些类的头文件。这样做可以尽量降低类之间的耦合(coupling)。
  • 有时无法使用向前声明,比如要声明某个类遵循一项协议。这种情况下,尽量把“该类遵循的某协议”这条声明移至“class-continuation分类”中,如果不行的话,就把协议单独放在一个头文件中,然后将其引入。

猜你喜欢

转载自blog.csdn.net/qq_28285625/article/details/88978390