objective-C中@class和#import的區別

We can import class declaration with #import:

#import "SomeClass.h" 

or declare with @class:

@classSomeClass; 

What's the difference and when we should use each of them?

 

Answer

"Import" links the header file it contains. Everything in the header, including property definitions, method declarations and any imports in the header are made available. Import provides the actual definitions to the linker.

@class by contrast just tells the linker not to complain it has no definition for a class. It is a "contract" that you will provide a definition for the class at another point.

Most often you use @class to prevent a circular import i.e. ClassA refers to ClassB so it imports ClassB.h in its own ClassA.h but ClassB also refers to ClassA so it imports ClassA.h in ClassB.h. Since the import statement imports the imports of a header, this causes the linker to enter an infinite loop.

Moving the import to the implementation file (ClassA.m) prevents this but then the linker won't recognize ClassB when it occurs in ClassA.h. The@class ClassB;directive tells the linker that you will provide the header for ClassB later before it is actually used in code.

當有兩個類A,類B。在類A.h中#import類B.h。然後當我們寫類B的時候,我們又需要用到類A的時候。使用類A.h包含在類B.h中,這樣當在編譯的時候,編譯器就會重複、循環地在A.h 和B.h中來回的加載。此時,我們可以使用這樣來避免出現這種情況。

在類A.h中,我們可以包含類B.h,但在類B.h中當我們需要使用類A時,我們可以使用@class A,這只是告訴編譯器,你爲類B提供了一個類A的定義,其他的都沒做。這樣就不會存在重複循環調用了。

其實,在類A.h中如果不會用到類B時,只是在A.m中用到類B時,你可以在A.m中#import B.h,只有當需要在類A.h中要用到類B時,才使用@class B.


二者的區別在於:

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

2.在頭文件中, 一般只需要知道被引用的類的名稱就可以了。 不需要知道其內部的實體變量和方法,所以在頭文件中一般使用@class來聲明這個名稱是類的名稱。 而在實現類裏面,因爲會用到這個引用類的內部的實體變量和方法,所以需要使用#import來包含這個被引用類的頭文件。

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

4.如果有循環依賴關係,如:A–>B, B–>A這樣的相互依賴關係,如果使用#import來相互包含,那麼就會出現編譯錯誤,如果使用@class在兩個類的頭文件中相互聲明,則不會有編譯錯誤出現。

所以,一般來說,@class是放在interface中的,只是爲了在interface中引用這個類,把這個類作爲一個類型來用的。 在實現這個接口的實現類中,如果需要引用這個類的實體變量或者方法之類的,還是需要import在@class中聲明的類進來.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章