美文网首页
2: 在类的头文件中尽量少引用其他头文件

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

作者: KKLinJJ | 来源:发表于2017-04-10 11:47 被阅读137次

    与C、C++一样,Objective-C也使用“头文件”和“实现文件”来区隔代码。用Objective-C语言编写类的标准方式:以类名做文件名,分别创建2个文件,头文件后缀.h,实现文件.m
    用Objective-C语言编写任何类几乎都需要引入Foundation.h,如果不在该类本身引入这个文件的话,那么就要引入与其超类所属框架相对应的"基本头文件"


    使用向前声明延后引入头文件时机

    比如存在CWGPerson类和CWGEmployer类。
    每个CWGPerson实例都应该有一个CWGEmployer.
    于是我们一般会这样写:(直接在.h中引入头文件)

    #import "CWGEmployer.h" 
    @interfance  CWGPerson : NSObject 
    @property (nonatomic, strong) CWGEmployer *employer; 
    @end 
    

    这样做不是不行,只是不够优雅罢了.因为在编译一个使用了CWGPerson类的文件时,不需要知道CWGEmployer类的全部细节,只需要知道有一个类名CWGEmployer就可以了.于是我们还可以这样写:

    //类CWGPerson头文件
    @class CWGEmployer
    @interfance  CWGPerson : NSObject
    @property (nonatomic, strong) CWGEmployer *employer;
    @end
    
    CWGPerson.m实现文件中则需要引入CWGEmployer类的头文件,因为使用的时候,则必须知道其所有的细节.
    
    //类CWGPerson实现文件
    #import "CWGPerson.h"
    #import "CWGEmployer.h"
    @implementation CWGPerson
    // Implementation of methods
    @end
    
    • 向前声明减少引入头文件的数量,减少了编译时间

    将引入头文件的时机尽量延后, 只在确有需要时才真正引入,这样可以减少类的使用者所需引入头文件的数量.假如把CWGEmployer.h引入到CWGPerson.h中,那么只要引入CWGPerson.h,就会引入CWGEmployer.h的全部内容.如此持续下去,则要引入很多根本用不到的内容,还增加了编译时间.

    • 向前声明还避免了两个类相互引用的问题.

    例如CWGEmployer.m中增加了方法:

    • (void)addEmployee:(CWGPerson *)person;

    如果CWGPerson和CWGEmployer,都将彼此头文件引入到自己头文件中,这时候编译CWGEmployer,编译器必须知道CWGPerson这个类,而要编译CWGPerson,又必须知道CWGEmployer.这时候就会导致"循环引用".虽然使用#import不会导致死循环(#include会),但是这意味着2个类有一个是无法编译成功的。
    分析:当类A引用类B,类B又需要引用类A的时候,如果我们都在.h头文件中引用对方的头文件,那么就会出现头文件循环引用的问题,实际上使用#import而非#include指令虽然不会导致死循环,但却意味着两个类中有一个无法被正确编译而报错。

    相互引入头文件导致编译报错

    解决方案:(目的是实现两个文件编译时刻不在相互引用对方)
    1.在其中一个类.h头文件使用@class关键字向前声明另一个类,在该类.m文件中再使用#import引入头文件,另一个类正常引用就行。
    2.在两个类的.h头文件中均使用@class,在两个类的.m实现文件中再使用#import引入对应的头文件。

    一些必须引入头文件的情况
    有些时候必须引入头文件:
    1.该类继承了某个超类,则必须引入定义那个超类的头文件。
    2.该类遵循某协议,也要引入该协议对应的头文件
    

    如果你写的类继承某个超类,则必须引入定义那个超类的头文件.
    如果要声明你写的那个类遵从某个协议(protocol),那么该协议必须有完整的定义.且不能使用"向前声明".因为"向前声明"只能告诉编译器有这么个协议,但是编译器这时要知道这个协议中定义的方法.例如:

    #import "CWGShape.h"
    #import "CWGDrawable.h"
    @interface CWGRectangle : CWGShape  <CWGDrawable>
    @property (nonatomic, assign) CGFloat width;  ///< 宽
    @property (nonatomic, assign) CGFloat height; ///< 高
    @end
    
    其中#import "CWGDrawable.h"是难免的.
    
    #####总结:
    
    * 除非确有必要,否则不要引入头文件.一般说来,应该在某个类的头文件中使用"向前声明"来提及别的类.并在实现文件中引入那些类的头文件,这样做可以尽量降低类之间的耦合性.
    
    * 有时无法使用"向前声明",比如某个类要遵从某个协议,这种情况下,尽量把"该类遵循某协议"的声明移至到"延展"中(class - continuation 分类).如果还不行,就把协议单独放在一个头文件中,然后将其引入.

    相关文章

      网友评论

          本文标题:2: 在类的头文件中尽量少引用其他头文件

          本文链接:https://www.haomeiwen.com/subject/hjnhattx.html