Objective-C入門學(xué)習(xí)基礎(chǔ) 類聲明和定義
Objective-C入門學(xué)習(xí)基礎(chǔ) 類聲明和定義是本文要介紹的內(nèi)容,很詳細的為友們介紹Objective-C學(xué)習(xí)基礎(chǔ),不多說我們先來看內(nèi)容。
編譯處理指令
既然Objective-C是面向?qū)ο蟮某绦蛘Z言,所以理應(yīng)支持可重用的數(shù)據(jù)和函數(shù)的封裝體,即類。
類是在結(jié)構(gòu)體的基礎(chǔ)上發(fā)展的產(chǎn)物,結(jié)構(gòu)體只能處理數(shù)據(jù),在結(jié)構(gòu)體之上增加對該數(shù)據(jù)處理的函數(shù),就構(gòu)成類的概念。類使程序總能提供對數(shù)據(jù)專門處理函數(shù)的安全調(diào)用,使得一系列的機能作為一個子系統(tǒng)供安全且重復(fù)的使用。
像結(jié)構(gòu)體一樣,類在使用之前必須先聲明,但是Objective-C并沒有像其他面向?qū)ο笳Z言那樣提供聲明類的專用關(guān)鍵字或者語法,而是用編譯處理指令來實現(xiàn),特征是類聲明語句都須以@符號開始。
類聲明的編譯處理指令以@interface開始,以@end結(jié)尾,在這之間代碼便是類變量的定義和方法的聲明。類的聲明和定義比其他語言復(fù)雜,這會讓剛開始學(xué)習(xí)Objective-C的人非常困惑(準確的說,其他語言如Java只需定義類而不用聲明,而Objective-C需要先聲明再定義)。
- @interface 類名 : 父類名
- {
- 實例變量定義
- ...
- }
- 方法聲明
- @end
這就是Objective-C類聲明的語法結(jié)構(gòu),其中實例變量是供類內(nèi)部使用的變量,和結(jié)構(gòu)體的成員變量相似,但是實例變量不能從類的外部使用,原則上只能被類內(nèi)部的方法使用(當(dāng)然只是原則上)。類可以沒有實例變量,這時{}可以省略。
類的方法(注意和類方法的區(qū)別)是專屬該類的方法,與普通函數(shù)的區(qū)別是:類的方法可以操作類內(nèi)部的實例變量。
緊接類名后邊的是父類名,也就是說可以指定類的父類,構(gòu)成繼承。繼承使類可繼承使用父類的機能,而僅定義父類沒有的機能。比如父類是抽象的哺乳動物類,如果定義貓類的時候,可以繼承哺乳動物這個父類,而在貓類中只定義貓區(qū)別與普通哺乳動物類的特有功能即可。
父類可以不指定,這時編譯器會為類提供一個缺省的類,即根類。
Objective-C的根類隨具體編譯器的不同而有所不同,GCC編譯器中是Object,Mac OS X的Cocoa編譯環(huán)境中則是NSObject,除非自己開發(fā)根類時可以不指定父類,一般情況下都要采用系統(tǒng)提供的根類作為父類。僅在根類開發(fā)時,類的定義可以如下(沒有父類):
- @interface 類名
- {
- 實例變量聲明
- ...
- }
類方法聲明
- @end
為什么所有的類都必須繼承自一個共同的根類,那是因為根類提供了類正常動作所必須的一些基本機能,比如內(nèi)存的取得和釋放,如果沒有根類,那么所有的類都要自己去完成這些基本的工作,會使類非常的復(fù)雜而不能專注于具體業(yè)務(wù)(后面還會具體說明)。
類中實例變量的聲明和普通C語言的變量聲明沒有什么區(qū)別,但是類方法的聲明則差別很大,語法如下:
-(返回值類型) 方法名 : 臨時參數(shù)列…;
首先,最左邊的減號,代表該方法是類的實例方法,如果是加號則代表該方法為類方法。這里須記住一點:普通定義類的時候,方法前用減號即實例方法即可,類方法是可以不用生成實例而直接調(diào)用的方法。實例方法和類方法的區(qū)別后面會詳細說明。
其次,返回值類型要放在()中,如果函數(shù)需要參數(shù)的時候,參數(shù)的類型也要放到()中,然后緊接參數(shù)名,如果有多個參數(shù),則用逗號隔開。
C語言函數(shù)的缺省返回值類型是int型,在Objective-C中新追加了一個id型的對象類型作為缺省函數(shù)的返回值類型。雖然返回值可以不指定,但一般不建議這么做。如果沒有返回值,則要用(void)做明確說明。
- @interface Test : Object
- (void)method;
- @end
在這個Test類聲明中,聲明了一個沒有返回值,沒有參數(shù)的方法method,類和方法以及變量的命名規(guī)則和C語言一樣,以字母或下劃線開頭。但是習(xí)慣上類名的首字母大寫,方法名則全部小寫。
到這里,類的聲明已經(jīng)做好了,但是方法method只是聲明了名稱和類型,具體實現(xiàn)的代碼怎么寫呢?事實上,Objective-C將類的聲明和定義完全分開,在類的聲明中,只能定義實例變量和方法名及類型,具體的實現(xiàn)要用到@implementation這個編譯處理指令中進行。
- @implementation 類名
實例方法定義
- @end
- @implementation
這個編譯指令具體定義@interface中聲明的方法,聲明過的方法,必須在這里具體定義。
類的實例化
類經(jīng)過聲明和定義,但是還不能直接使用,使用類之前必須分配具體的內(nèi)存領(lǐng)域且進行適當(dāng)?shù)某跏蓟?。根?jù)類的聲明具體分配一塊內(nèi)存,這個過程叫實例化,而具體分配的這塊內(nèi)存,叫做實例或者對象。
C++或者Java中為我們提供好了new運算符,可以自動由類生成實例并完成初始化,而Objective-C實例化竟然也要類自己完成(即需要類給出實例化自己的方法)。實例化需要調(diào)查生成對象的大小,申請內(nèi)存完成復(fù)雜的初始化,這些任務(wù)對普通用戶太難了,不過幸好編譯環(huán)境為我們提供了根類(Object)來幫助完成這些功能,這也是為什么所有的類都必須繼承自根類的原因(否則實例化方法要自己寫)。
在根類Object中,定義了實例化根類以及繼承自根類的類的類方法alloc,一般的實例方法,必須先有實例才能調(diào)用,但是類方法,沒有實例也可以使用。所以類方法alloc雖然沒有實例,也是可以正常調(diào)用的。鑒于alloc是用來生成實例的類方法,所以也常常也被稱作工廠方法。
- +alloc;
這是Object中alloc的聲明,+開頭,說明是一個類方法,缺省返回值為id類型,沒有參數(shù)。
id型是代表對象的廣義類型,什么類型的對象都可以放入id型的對象中。
下面,就要調(diào)用alloc類方法,生成實例了,但是怎樣寫呢?如果熟悉C++,可能會首先想到下面的調(diào)用方式:
- id obj =類名.alloc();
遺憾的是,這種寫法是錯誤的,和大多數(shù)面向?qū)ο笳Z言的調(diào)用方式不同,Objective-C有自己獨特的調(diào)用方式:
- [類名 類方法名:參數(shù)序列...]
如果是調(diào)用實例方法的時候,要將類名換成實例名,其中[ ]在Objective-C中被稱為消息,這是因為在Objective-C中,從對象調(diào)用方法的時候,不是直接調(diào)用,而是向?qū)ο蟀l(fā)送特定的消息,對象接收到消息后,根據(jù)消息內(nèi)容啟動相應(yīng)的方法,這種方式雖然帶來了程序的柔軟性,但是比C語言的調(diào)用方式帶來額外的消耗,因為程序執(zhí)行時要耗費時間檢索特定的方法然后啟動。
- #import <stdio.h>
- #import <objc/Object.h>
- @interface Test : Object
- - (void)method;
- @end
- @implementation Test
- - (void)method {
- printf("Kitty on your lap\n");
- }
- @end
- int main() {
- id obj = [Test alloc];
- [obj method];
- return 0;
- }
上面的程序是一個Objective-C簡單但完整的類實例例子,@interface完成類的聲明,繼承自根類Object。@implementation完成類的定義,具體定義method的實現(xiàn)方法。
類聲明和定義準備好之后,在main函數(shù)中,首先定義id型的對象變量obj,然后調(diào)用Test類的父類Object的類方法alloc生成實例,***調(diào)用實例obj的實例方法method,實現(xiàn)輸出打印。
另外,如果不定義obj變量(或者說Test的實例只在這里使用一次就不用了),也可以像下面的寫法:
- [[Test alloc] method]
注:像上面的程序片段一樣,雖然對類的聲明和定義的具體位置沒有要求,但是習(xí)慣上把類的聲明放到頭文件中,類的定義放到和類名同名的.m文件中。
原帖發(fā)布地址(PDF版): http://bbs.goocnjp.com/thread-338.html
小結(jié):關(guān)于Objective-C入門學(xué)習(xí)基礎(chǔ) 類聲明和定義的內(nèi)容介紹完了,希望本文對你有所幫助!