在類的頭文件中盡量少引入其他頭文件

聲明:此文章是做個(gè)人筆記查閱用的,不是供他人來抨擊抄襲的!!!

與C、C++一樣,Objective-C也使用“頭文件”和“實(shí)現(xiàn)文件”來區(qū)隔代碼。用Objective-C語言編寫類的標(biāo)準(zhǔn)方式:以類名做文件名,分別創(chuàng)建2個(gè)文件,頭文件后綴.h,實(shí)現(xiàn)文件.m
用Objective-C語言編寫任何類幾乎都需要引入Foundation.h,如果不在該類本身引入這個(gè)文件的話,那么就要引入與其超類所屬框架相對應(yīng)的"基本頭文件".


比如編寫了一個(gè)CWGPerson的類,過了一段時(shí)間有創(chuàng)建了一個(gè)CWGEmployer的新類,然后每個(gè)CWGPerson實(shí)例都應(yīng)該有一個(gè)CWGEmployer.于是我們一般會這樣寫:

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

這樣做不是不行,只是不夠優(yōu)雅罷了.因?yàn)樵诰幾g一個(gè)使用了CWGPerson類的文件時(shí),不需要知道CWGEmployer類的全部細(xì)節(jié),只需要知道有一個(gè)類名CWGEmployer就可以了.于是我們還可以這樣寫:

@class CWGEmployer
@interfance  CWGPerson : NSObject
@property (nonatomic, strong) CWGEmployer *employer;
@end

CWGPerson類的實(shí)現(xiàn)文件,也就是CWGPerson.m文件則需要引入CWGEmployer類的頭文件,因?yàn)橐褂煤笳?則必須知道期所有的接口細(xì)節(jié).

#import "CWGPerson.h"
#import "CWGEmployer.h"

@implementation CWGPerson
// Implementation of methods
@end

將引入頭文件的時(shí)機(jī)盡量延后, 只在確有需要時(shí)才真正引入,這樣可以減少類的使用者所需引入頭文件的數(shù)量.假如把CWGEmployer.h引入到CWGPerson.h中,那么只要引入CWGPerson.h,就會引入CWGEmployer.h的全部內(nèi)容.如此持續(xù)下去,則要引入很多根本用不到的內(nèi)容,還增加了編譯時(shí)間.

向前聲明還避免了兩個(gè)類相互引用的問題,例如CWGEmployer.m中增加了方法:

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

這時(shí)候編譯CWGEmployer,編譯器必須知道CWGPerson這個(gè)類,而要編譯CWGPerson,又必須知道CWGEmployer.這時(shí)候就會導(dǎo)致"循環(huán)引用".雖然使用#import不會導(dǎo)致死循環(huán)(#include會),但是這意味著2個(gè)類有一個(gè)是無法編譯成功的,如果不信,讀者可以嘗試下.


還有一點(diǎn)需要注意,那就是有時(shí)候必須要在頭文件中引入其他頭文件,如果你寫的類繼承某個(gè)超類,則必須引入定義那個(gè)超類的頭文件.同理,如果要聲明你寫的那個(gè)類遵從某個(gè)協(xié)議(protocol),那么該協(xié)議必須有完整的定義.且不能使用"向前聲明".因?yàn)?向前聲明"只能告訴編譯器有這么個(gè)協(xié)議,但是編譯器這時(shí)要知道這個(gè)協(xié)議中定義的方法.例如:

#import "CWGShape.h"
#import "CWGDrawable.h"

@interface CWGRectangle : CWGShape  <CWGDrawable>
@property (nonatomic, assign) CGFloat width;  ///< 寬
@property (nonatomic, assign) CGFloat height; ///< 高
@end

其中#import "CWGDrawable.h"是難免的.對于這種情況,最好是把協(xié)議單獨(dú)放在一個(gè)頭文件里.但是把CWGDrawable協(xié)議放在某個(gè)打的頭文件里,那么只要引入此協(xié)議,必定會引入頭文件中的全部內(nèi)容,如此一來又會出現(xiàn)上面講的問題.

然而對于委托協(xié)議,就不用單獨(dú)寫到一個(gè)頭文件里了.這種情況下,協(xié)議只有和接受協(xié)議的類放在一起才有意義.此時(shí)最好能在實(shí)現(xiàn)文件(.m文件)中聲明此類實(shí)現(xiàn)了該委托協(xié)議.并把這段代碼放在"class - continuation 分類"里.這樣的話, 只要在實(shí)現(xiàn)文件中引入包含委托協(xié)議的頭文件即可,而不需要將其放在公共頭文件里.

每次在頭文件張引入其他頭文件之前,都問問自己這樣做是否真的有必要.如果可以使用"向前聲明"取代引入,那么就不要引入.若因?yàn)橐獙?shí)現(xiàn)屬性, 實(shí)例變量或要遵循協(xié)議必須引入頭文件,則應(yīng)盡量移至到class - continuation 分類中.這樣做不僅能縮減編譯時(shí)間,而且能降低彼此的依賴性.如果依賴過于復(fù)雜,則會給維護(hù)帶來麻煩.而且如果只想把代碼的某個(gè)部分開放為公共的API,太過復(fù)雜的依賴關(guān)系也會出問題.

總結(jié)

  • 除非確有必要,否則不要引入頭文件.一般說來,應(yīng)該在某個(gè)類的頭文件中使用"向前聲明"來提及別的類.并在實(shí)現(xiàn)文件中引入那些類的頭文件,這樣做可以盡量降低類之間的耦合性.

  • 有時(shí)無法使用"向前聲明",比如某個(gè)類要遵從某個(gè)協(xié)議,這種情況下,盡量把"該類遵循某協(xié)議"的聲明移至到"延展"中(class - continuation 分類).如果還不行,就把協(xié)議單獨(dú)放在一個(gè)頭文件中,然后將其引入.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容