Objective-C 學習記錄
2 {
3 memberDeclarations;
4 }
5 methodDeclarations;
6 @end
結構還是比較清楚. 包圍在大括號之內的就是實例變量(instance variables).
Objective-C用來區分實例方法和類方法的手段就是方法定義前的標誌, "-"(minus)表示是實例方法, "+"(plu)表示是類方法.
方法定義的結構如下:
需要注意的地方是: 在方法名後如果跟著一個分號, 表示後麵有參數, 否則就表示沒有參數傳進來.
定義完了一個類之後, 就要具體的實現他了. 就好像是C++中在.h文件中定義完類, 然後就去.cpp中完成具體的實現. 隻不過這裏要將.cpp換成是.m罷了.
2 methodDefinitions
3 @end
還要注意一點, 不同於其他的語言, 比如我們經常使用的C, C++, Java, Python等, 習慣於使用"."來表示方法調用, Objective-C中的方法調用形式是使用中括號"[]":
這個可能是學習Objective-C中比較別扭的一個地方吧.
Objective-C中有一種類型稱為:id.
被聲明成該類型的變量, 可以用來存儲任何類型的對象, 感覺非常像C, C++中的空指針.
方法聲明中, 如果不指定範圍類型和參數類型, 默認就是id.
id主要是用在多態和動態綁定上.
既然id可以用來表示任何類型的數據,為什麼在編寫代碼的時候不將所有的變量類型都聲明為id類型呢?有這麼幾個原因:
- 在變量聲明的時候,如果指定了具體類型,比如int,float, ClassName等,稱為靜態類型聲明。這樣,編譯器在編譯階段就能夠了解到變量類型,從而更好地進行編譯優化等工作。
- 如果使用id作為變量類型,那麼類型檢查,方法查找等工作就是在運行期進行的。而這樣,如果程序中存在錯誤,也隻能在運行時發現。一旦投入到生產環境,將是非常可怕的。
- 最簡單的原因就是為了代碼的可讀性,聲明成id類型當然不如聲明成具體類型直觀了。
Objective-C關於麵向對象這部分,多了幾個概念,不同於之前學過的C++,有必要在這裏詳細說明一下。
一、Category:
總的來說,category就是對已經存在的類進行一些修改,方法的重載(還有些不同於繼承),添加新方法等。
基本語法如下:
methodDeclaration;
@end
@implementation ClassName (CategoryName)
methodDefinition;
@end
這樣,ClassName在CategoryName下就有了新的方法,也就是說,對原有的ClassName進行了擴充。
但是,這裏還有幾點需要注意:
- 雖然category可以訪問類的實例變量,去不能創建新的實例變量,如果要創新的實例變量,請使用繼承;
- 在category中,不提倡對原有方法進行重載。原因非常簡單,在category中進行重載,無法對原方法進行訪問,而繼承中可以使用super。如果真的需要對原方法進行重載,請考慮繼承;
- 一個類可以定義多個category,但是如果不同category中存在相同方法,編譯器無法決定使用哪個category;
- 在定義category時,我們可以僅僅給出方法定義,而不需要給出具體的實現。這在程序增量開發時是非常有幫助的;
- category是可以被繼承的。在某個父類中定義了category,那麼他所有的子類都具有該category;
二、Posing:
通過postAs方法,可以將一個類型“假扮”成另一種類型。
當有消息發送給ClassB的實例時,那麼就會調用ClassA中的相應方法(當然,該方法必須存在)。這樣,ClassA的就成功的模擬了ClassB。
三、Protocol:
Protocol有點Java裏interface的味道。定義了一組方法,而不提供具體實現。隻有那些“遵守”(conform to)或“采用”(adopt)了這些Protocol的類來給出自己的實現。
Protocol的語法如下:
methodDeclaration;
@end
而在類聲明時,語法如下:
一個類可以采用多個Protocol。
Protocol也可以采用別的Protocol:
當然,category也可以在定義時指定采用的Protocol:
在Objective-C裏要注意一點, 文件依賴一般都是通過import來導入的, 如此一來, 在工程較大, 文件定義較多的時候, 會需要在編譯階段消耗很多時間. 比如A.h import了 B.h, 一旦A文件有了改動, 那麼B也會在編譯時重新進行編譯. 如果有上百個文件相互一來, 造成cascade of changes, 那麼編譯過程可想而知.
大多時候, 我們隻想引用一個類, 比如集成或者複合. 這個時候最好就是使用
這個關鍵字, 他會告訴編譯器, hey dude, 我隻想引用這個class, 不想知道他的實現細節, please calm down.
還有一種情況, 循環引用, 如果A引用了B, B又引用了A, 如果使用import,編譯器就會出錯. 而@class會讓兩者和平共處.
但是, 在繼承的時候, 還是需要使用import, 為什麼呢? 很簡單, 編譯器需要知道繼承的父類的具體信息. 有那些變量, 方法等等. 如果這個時候使用@class, 就不合時宜了.
最後更新:2017-04-02 22:14:28