拆分接口和實現
類的@interface指令、公共struct定義、enum常亮、#define和extern全局變量等代碼通常放在頭文件.h文件中。
所有的實現內容,例如@implementation指令、全局變量的定義、私有struct等代碼都放在.m文件中。
如果用.mm做文件擴展名,編譯器就會認爲你使用Objective-C++編寫的代碼,這樣就可以同時使用C++和Objective-C來編程了。導入頭文件
導入頭文件有兩種方法:使用引號或者尖括號。
帶尖括號的語句用於引用系統頭文件,是隻讀的。
而帶引號的語句說明導入的是項目本地的頭文件,是可編輯的。使用跨文件依賴關係
依賴關係(dependency)是兩個實體之間的一種關係。
依賴關係存在於兩個或多個文件之間。
導入頭文件使頭文件和源文件之間建立了一種緊密的依賴關係。如果頭文件有任何變化,那麼所有依賴它的文件都得重新編譯。
依賴關係是傳遞的,頭文件之間也可以相互依賴。
文件導入過於混亂會使依賴關係混亂,從而導致重新編譯花費很長時間。所以巧妙的使用@class指令,可以減少必須導入的頭文件的數量,從而縮短編譯時間。@class
Objective-C引入了@class關鍵字,用來告訴編譯器:“這是一個類,所以我只會通過指針來引用它”,這樣編譯器就不必知道關於這個類的更多信息,只要瞭解它是通過指針來引用的即可。
例如:
#import <Cocoa/Cocoa.h>
@interface Car : NSObject
-(void)setEngine:(Engine *)newEngine;
-(Engine *)engine;
-(void)setTire:(Tire *)newTire andIndex:(int)index;
-(Tire *)tireAtIndex:(int)index;
@end //Car
如果我們現在想使用Car.h頭文件,會得到錯誤消息,例如error: expected a type “Tire”,編譯器是說“我無法理解這個”。我們有兩種方法來解決,第一種是在頭文件中#import語句導入Tire.h和Engine.h,這樣編譯器會獲取這兩個類的許多信息。
此外,還有一個更好的方法。因爲在Car.h文件中,它只是通過指針引用了Tire類和Engine類,所以我們可以用@class來實現。
#import <Cocoa/Cocoa.h>
@class “Tire.h"
@class “Engine.h"
@interface Car : NSObject
-(void)setEngine:(Engine *)newEngine;
-(Engine *)engine;
-(void)setTire:(Tire *)newTire andIndex:(int)index;
-(Tire *)tireAtIndex:(int)index;
@end //Car
這樣就足以告知編譯器處理Car類的@interface部分所需要的全部信息了。
@class創建了一個前向引用。這是在告訴編譯器,只能使用被聲明的符號,而不能涉及類的任何細節。
如果有循環依賴關係,@class也很管用。即A類使用了B類,B類也使用了A類,如果試圖通過#import語句讓這兩個類相互引用,那麼就會出現編譯錯誤。但是如果在A.h文件中使用@classB,在 B.h文件中使用@class A,那麼這兩個類就可以相互引用了。