OBJECTIVE-C入門(2) 類的聲明和定義

來源:互聯網
上載者:User

編譯處理指示 

    既然Objective-C是物件導向的程式語言,所以理應支援可重用的資料和函數的封裝體,即類。

    類是在結構體的基礎上發展的產物,結構體只能處理資料,在結構體之上增加對該資料處理的函數,就構成類的概念。類使程式總能提供對資料專門處理函數的安全調用,使得一系列的機能作為一個子系統供安全且重複的使用。

    像結構體一樣,類在使用之前必須先聲明,但是Objective-C並沒有像其他物件導向語言那樣提供聲明類的專用關鍵字或者文法,而是用編譯處理指示來實現,特徵是類聲明語句都須以@符號開始。

    類聲明的編譯處理指示以@interface開始,以@end結尾,在這之間代碼便是類變數的定義和方法的聲明。類的聲明和定義比其他語言複雜,這會讓剛開始學習Objective-C的人非常困惑(準確的說,其他語言如Java只需定義類而不用聲明,而Objective-C需要先聲明再定義)。

@interface 類名 : 父類名 {
執行個體變數定義
...
}
方法聲明
@end

 

    這就是Objective-C類聲明的文法結構,其中執行個體變數是供類內部使用的變數,和結構體的成員變數相似,但是執行個體變數不能從類的外部使用,原則上只能被類內部的方法使用(當然只是原則上)。類可以沒有執行個體變數,這時{}可以省略。

    類的方法(注意和類方法的區別)是專屬該類的方法,與普通函數的區別是:類的方法可以操作類內部的執行個體變數。

    緊接類名後邊的是父類名,也就是說可以指定類的父類,構成繼承。繼承使類可繼承使用父類的機能,而僅定義父類沒有的機能。比如父類是抽象的哺乳動物類,如果定義貓類的時候,可以繼承哺乳動物這個父類,而在貓類中只定義貓區別與普通哺乳動物類的特有功能即可。

    父類可以不指定,這時編譯器會為類提供一個預設的類,即根類。

    Objective-C的根類隨具體編譯器的不同而有所不同,GCC編譯器中是Object,Mac OS X的Cocoa編譯環境中則是NSObject,除非自己開發根類時可以不指定父類,一般情況下都要採用系統提供的根類作為父類。僅在根類開發時,類的定義可以如下(沒有父類):

@interface 類名
{
執行個體變數聲明
...
}
類方法聲明
@end

 

    為什麼所有的類都必須繼承自一個共同的根類,那是因為根類提供了類正常動作所必須的一些基本機能,比如記憶體的取得和釋放,如果沒有根類,那麼所有的類都要自己去完成這些基本的工作,會使類非常的複雜而不能專註於具體業務(後面還會具體說明)。

    類中執行個體變數的聲明和普通C語言的變數聲明沒有什麼區別,但是類方法的聲明則差別很大,文法如下:

-(傳回值類型)  方法名 :  臨時參數列…;

    首先,最左邊的減號,代表該方法是類的執行個體方法,如果是加號則代表該方法為類方法。這裡須記住一點:普通定義類的時候,方法前用減號即執行個體方法即可,類方法是可以不用產生執行個體而直接調用的方法。執行個體方法和類方法的區別後面會詳細說明。

    其次,傳回值類型要放在()中,如果函數需要參數的時候,參數的類型也要放到()中,然後緊接參數名,如果有多個參數,則用逗號隔開。

    C語言函數的預設傳回值類型是int型,在Objective-C中新追加了一個id型的物件類型作為預設函數的傳回值類型。雖然傳回值可以不指定,但一般不建議這麼做。如果沒有傳回值,則要用(void)做明確說明。

@interface Test : Object
- (void)method;
@end

    在這個Test類聲明中,聲明了一個沒有傳回值,沒有參數的方法method,類和方法以及變數的命名規則和C語言一樣,以字母或底線開頭。但是習慣上類名的首字母大寫,方法名則全部小寫。

    到這裡,類的聲明已經做好了,但是方法method只是聲明了名稱和類型,具體實現的代碼怎麼寫呢?事實上,Objective-C將類的聲明和定義完全分開,在類的聲明中,只能定義執行個體變數和方法名及類型,具體的實現要用到@implementation這個編譯處理指示中進行。

@implementation 類名
執行個體方法定義
...
@end

    @implementation這個編譯指令具體定義@interface中聲明的方法,聲明過的方法,必須在這裡具體定義。 

 

類的執行個體化

 

    類經過聲明和定義,但是還不能直接使用,使用類之前必須分配具體的記憶體領域且進行適當的初始化。根據類的聲明具體分配一塊記憶體,這個過程叫執行個體化,而具體分配的這塊記憶體,叫做執行個體或者對象。

    C++或者Java中為我們提供好了new運算子,可以自動由類產生執行個體並完成初始化,而Objective-C執行個體化竟然也要類自己完成(即需要類給出執行個體化自己的方法)。執行個體化需要調查產生對象的大小,申請記憶體完成複雜的初始化,這些任務對普通使用者太難了,不過幸好編譯環境為我們提供了根類(Object)來協助完成這些功能,這也是為什麼所有的類都必須繼承自根類的原因(否則執行個體化方法要自己寫)。

    在根類Object中,定義了執行個體化根類以及繼承自根類的類的類方法alloc,一般的執行個體方法,必須先有執行個體才能調用,但是類方法,沒有執行個體也可以使用。所以類方法alloc雖然沒有執行個體,也是可以正常調用的。鑒於alloc是用來產生執行個體的類方法,所以也常常也被稱作Factory 方法。

+alloc;

    這是Object中alloc的聲明,+開頭,說明是一個類方法,預設傳回值為id類型,沒有參數。

    id型是代表對象的廣義類型,什麼類型的對象都可以放入id型的對象中。

    下面,就要調用alloc類方法,產生執行個體了,但是怎樣寫呢?如果熟悉C++,可能會首先想到下面的調用方式:

id obj =類名.alloc();

    遺憾的是,這種寫法是錯誤的,和大多數物件導向語言的調用方式不同,Objective-C有自己獨特的調用方式:

[類名 類方法名:參數序列...]

 

    如果是調用執行個體方法的時候,要將類名換成執行個體名,其中[  ]在Objective-C中被稱為訊息,這是因為在Objective-C中,從對象調用方法的時候,不是直接調用,而是向對象發送特定的訊息,對象接收到訊息後,根據訊息內容啟動相應的方法,這種方式雖然帶來了程式的柔軟性,但是比C語言的調用方式帶來額外的消耗,因為程式執行時要耗費時間檢索特定的方法然後啟動。

#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的實現方法。

    類聲明和定義準備好之後,在main函數中,首先定義id型的物件變數obj,然後調用Test類的父類Object的類方法alloc產生執行個體,最後調用執行個體obj的執行個體方法method,實現輸出列印。

    另外,如果不定義obj變數(或者說Test的執行個體只在這裡使用一次就不用了),也可以像下面的寫法:

[[Test alloc] method]

註:像上面的程式片段一樣,雖然對類的聲明和定義的具體位置沒有要求,但是習慣上把類的聲明放到標頭檔中,類的定義放到和類名同名的.m檔案中。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.