與C、C++一樣话原,Objective-C也使用“頭文件”和“實現(xiàn)文件”來區(qū)隔代碼夕吻。用Objective-C語言編寫類的標(biāo)準(zhǔn)方式:以類名做文件名,分別創(chuàng)建2個文件,頭文件后綴.h,實現(xiàn)文件.m
用Objective-C語言編寫任何類幾乎都需要引入Foundation.h,如果不在該類本身引入這個文件的話,那么就要引入與其超類所屬框架相對應(yīng)的"基本頭文件"
使用向前聲明延后引入頭文件時機(jī)
比如存在CWGPerson類和CWGEmployer類。
每個CWGPerson實例都應(yīng)該有一個CWGEmployer.
于是我們一般會這樣寫:(直接在.h中引入頭文件)
#import "CWGEmployer.h"
@interfance CWGPerson : NSObject
@property (nonatomic, strong) CWGEmployer *employer;
@end
這樣做不是不行,只是不夠優(yōu)雅罷了.因為在編譯一個使用了CWGPerson類的文件時,不需要知道CWGEmployer類的全部細(xì)節(jié),只需要知道有一個類名CWGEmployer就可以了.于是我們還可以這樣寫:
//類CWGPerson頭文件
@class CWGEmployer
@interfance CWGPerson : NSObject
@property (nonatomic, strong) CWGEmployer *employer;
@end
CWGPerson.m實現(xiàn)文件中則需要引入CWGEmployer類的頭文件,因為使用的時候,則必須知道其所有的細(xì)節(jié).
//類CWGPerson實現(xiàn)文件
#import "CWGPerson.h"
#import "CWGEmployer.h"
@implementation CWGPerson
// Implementation of methods
@end
- 向前聲明減少引入頭文件的數(shù)量繁仁,減少了編譯時間
將引入頭文件的時機(jī)盡量延后, 只在確有需要時才真正引入,這樣可以減少類的使用者所需引入頭文件的數(shù)量.假如把CWGEmployer.h引入到CWGPerson.h中,那么只要引入CWGPerson.h,就會引入CWGEmployer.h的全部內(nèi)容.如此持續(xù)下去,則要引入很多根本用不到的內(nèi)容,還增加了編譯時間.
- 向前聲明還避免了兩個類相互引用的問題.
例如CWGEmployer.m中增加了方法:
- (void)addEmployee:(CWGPerson *)person;
如果CWGPerson和CWGEmployer涉馅,都將彼此頭文件引入到自己頭文件中,這時候編譯CWGEmployer,編譯器必須知道CWGPerson這個類,而要編譯CWGPerson,又必須知道CWGEmployer.這時候就會導(dǎo)致"循環(huán)引用".雖然使用#import不會導(dǎo)致死循環(huán)(#include會),但是這意味著2個類有一個是無法編譯成功的黄虱。
分析:當(dāng)類A引用類B稚矿,類B又需要引用類A的時候,如果我們都在.h頭文件中引用對方的頭文件捻浦,那么就會出現(xiàn)頭文件循環(huán)引用的問題晤揣,實際上使用#import而非#include指令雖然不會導(dǎo)致死循環(huán),但卻意味著兩個類中有一個無法被正確編譯而報錯朱灿。
解決方案:(目的是實現(xiàn)兩個文件編譯時刻不在相互引用對方)
1.在其中一個類.h頭文件使用@class關(guān)鍵字向前聲明另一個類昧识,在該類.m文件中再使用#import引入頭文件,另一個類正常引用就行盗扒。
2.在兩個類的.h頭文件中均使用@class跪楞,在兩個類的.m實現(xiàn)文件中再使用#import引入對應(yīng)的頭文件。
一些必須引入頭文件的情況
有些時候必須引入頭文件:
1.該類繼承了某個超類环疼,則必須引入定義那個超類的頭文件习霹。
2.該類遵循某協(xié)議,也要引入該協(xié)議對應(yīng)的頭文件
如果你寫的類繼承某個超類,則必須引入定義那個超類的頭文件.
如果要聲明你寫的那個類遵從某個協(xié)議(protocol),那么該協(xié)議必須有完整的定義.且不能使用"向前聲明".因為"向前聲明"只能告訴編譯器有這么個協(xié)議,但是編譯器這時要知道這個協(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"是難免的.
#####總結(jié):
* 除非確有必要,否則不要引入頭文件.一般說來,應(yīng)該在某個類的頭文件中使用"向前聲明"來提及別的類.并在實現(xiàn)文件中引入那些類的頭文件,這樣做可以盡量降低類之間的耦合性.
* 有時無法使用"向前聲明",比如某個類要遵從某個協(xié)議,這種情況下,盡量把"該類遵循某協(xié)議"的聲明移至到"延展"中(class - continuation 分類).如果還不行,就把協(xié)議單獨放在一個頭文件中,然后將其引入.