#import,#include及@class的區(qū)別

#import與#include的區(qū)別

#import比起#include的好處就是不會(huì)引起交叉編譯

for example 三個(gè)文件

文件A.h

文件B.h

文件C.h

文件C.h需要引入A.h、B.h ,文件B.h需要引入文件A.h,這樣就重復(fù)引用了A.h兩次,使用#import可以進(jìn)行優(yōu)化

#import指令是Object-C針對(duì)#include的改進(jìn)版本,#import確保引用的文件只會(huì)被引用一次,這樣就不會(huì)陷入遞歸包含的問題中。

#import與@class的區(qū)別

1.import會(huì)包含這個(gè)類的所有信息,包括實(shí)體變量和方法,而@class只是告訴編譯器,其后面聲明的名稱是類的名稱,至于這些類是如何定義的,暫時(shí)不用考慮,后面會(huì)再告訴你。

2.在頭文件中, 一般只需要知道被引用的類的名稱就可以了。 不需要知道其內(nèi)部的實(shí)體變量和方法,所以在頭文件中一般使用@class來聲明這個(gè)名稱是類的名稱。 而在實(shí)現(xiàn)類里面,因?yàn)闀?huì)用到這個(gè)引用類的內(nèi)部的實(shí)體變量和方法,所以需要使用#import來包含這個(gè)被引用類的頭文件。

3.在編譯效率方面考慮,如果你有100個(gè)頭文件都#import了同一個(gè)頭文件,或者這些文件是依次引用的,如A–>B, B–>C, C–>D這樣的引用關(guān)系。當(dāng)最開始的那個(gè)頭文件有變化的話,后面所有引用它的類都需要重新編譯,如果你的類有很多的話,這將耗費(fèi)大量的時(shí)間。而是用@class則不會(huì)。

4.如果有循環(huán)依賴關(guān)系,如:A–>B, B–>A這樣的相互依賴關(guān)系,如果使用#import來相互包含,那么就會(huì)出現(xiàn)編譯錯(cuò)誤,如果使用@class在兩個(gè)類的頭文件中相互聲明,則不會(huì)有編譯錯(cuò)誤出現(xiàn)。

所以,一般來說,@class是放在interface中的,只是為了在interface中引用這個(gè)類,把這個(gè)類作為一個(gè)類型來用的。 在實(shí)現(xiàn)這個(gè)接口的實(shí)現(xiàn)類中,如果需要引用這個(gè)類的實(shí)體變量或者方法之類的,還是需要import在@class中聲明的類進(jìn)來.

舉個(gè)例子說明一下。

在ClassA.h中

#import ClassB.h 相當(dāng)于#include整個(gè).h頭文件。如果有很多.m文件#import ClassA.h,那么編譯的時(shí)候這些文件也會(huì)#import ClassB.h增加了沒必要的#import,浪費(fèi)編譯時(shí)間。在大型軟件中,減少.h文件中的include是非常重要的。

如果

只是 ClassB 那就沒有include ClassB.h。僅需要在需要用到ClassB的.m文件中 #import ClassB.h

那么什么時(shí)候可以用呢?

如果ClassA.h中僅需要聲明一個(gè)ClassB的指針,那么就可以在ClassA.h中聲明

@ClassB

...

ClassB *pointer;

假設(shè),有兩個(gè)類:ClassA和ClassB,兩個(gè)之間相互使用到,即構(gòu)成了circular dependency(循環(huán)依賴)。如果在頭文件里面只用#import把對(duì)方的頭文件包含進(jìn)來(構(gòu)成circular inclusions,循環(huán)包含),則編譯器會(huì)報(bào)錯(cuò):

Expected specifier-qualifier-list before ‘ClassA’

或者

Expected specifier-qualifier-list before ‘ClassB’

為了避免循環(huán)包含,在ClassA.h文件里面用@class classB把classB包含進(jìn)來,同樣,在ClassB.h文件里面用@class ClassA把ClassA包含進(jìn)來。@class指令只是告訴編譯器,這是個(gè)類,保留個(gè)空間來存放指針就可以了。

接下來,很可能在ClassA.m和ClassB.m中會(huì)有訪問包含進(jìn)來對(duì)象的成員的情況,這時(shí)必須讓編譯器知道更多信息,比如那個(gè)類有些什么方法可以調(diào)用,就必須用#import,再次把用到的類包含進(jìn)來,告訴編譯器所需要的額外信息。

否則,編譯器會(huì)警告:

warning: receiver ‘ClassA’ is a forward class and corresponding @interface may not exist

還有另一種情況,使用有Categories的類,要在.h頭文件里用#import把Categories包含進(jìn)來。

總之,使用原則是:

頭文件里面只#import超類 消息文件里面#import需要發(fā)消息過去的類 其他地方就用@class轉(zhuǎn)向聲明

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容