學(xué)習(xí)Objective-C:入門手冊(cè)Objective-C是一種簡(jiǎn)單的計(jì)算機(jī)語言,設(shè)計(jì)為可以支持真正的面向?qū)ο缶幊?。Objective-C通過提供類定義,,方法以及屬性的語法,還有其他可以提高類的動(dòng)態(tài)擴(kuò)展能力的結(jié)構(gòu)等,,擴(kuò)展了標(biāo)準(zhǔn)的ANSI C語言,。類的語法和設(shè)計(jì)主要是基于Smalltalk,最早的面向?qū)ο缶幊陶Z言之一,。 如果你以前使用過其他面向?qū)ο缶幊陶Z言,,那么下面的信息可以幫助你學(xué)習(xí)Objective-C的基本語法。許多傳統(tǒng)的面向?qū)ο蟾拍?,例如封裝,,繼承以及多態(tài),在Objective-C中都有所體現(xiàn),。這里有一些重要的不同,,但是這些不同在這文章會(huì)表現(xiàn)出來,而且如果你需要還有更多詳細(xì)的信息存在,。 如果你從來沒有使用任何編程語言編過程序,,那么你至少需要在開始之前,對(duì)相關(guān)概念進(jìn)行一些基礎(chǔ)的了解。對(duì)象的使用和對(duì)象對(duì)象架構(gòu)是iPhone程序設(shè)計(jì)的基礎(chǔ),,理解他們?nèi)绾谓换?duì)創(chuàng)建你的程序非常重要,。想了解面向?qū)ο蟾拍畹模?qǐng)參看使用Objective-C進(jìn)行面向?qū)ο缶幊?。此外,,參看Cocoa基礎(chǔ)指南可以獲得Cocoa中的面向?qū)ο笤O(shè)計(jì)模式的信息。 想了解更多Objective-C語言和語法的細(xì)節(jié)介紹,,請(qǐng)參看Objective-C 2.0編程語言,。 Objective-C: C的超集Objective-C是ANSI版本C編程語言的超集,支持C的基本語法,。在C代碼中,,你定義頭文件和源代碼文件,從代碼實(shí)現(xiàn)細(xì)節(jié)分離公共聲明,。Objective-C頭文件使用的文件名列在表1中,。 表1 Objective-C代碼的文件擴(kuò)展名
字符串作為C語言的超集,,Objective-C支持C語言字符串方面的約定,。也就是說,單個(gè)字符被單引號(hào)包括,,字符串被雙引號(hào)包括,。然而,大多數(shù)Objective-C通常不使用C語言風(fēng)格的字符串。反之,,大多數(shù)框架把字符串傳遞給NSString對(duì)象,。NSString類提供了字符串的類包裝,包含了所有你期望的優(yōu)點(diǎn),,包括對(duì)保存任意長度字符串的內(nèi)建內(nèi)存管理機(jī)制,,支持Unicode,printf風(fēng)格的格式化工具,,等等,。因?yàn)檫@種字符串使用的非常頻繁,Objective-C提供了一個(gè)助記符可以方便地從常量值創(chuàng)建NSString對(duì)象,。要使用這個(gè)助記符,,你需要做的全部事情,是在普通的雙引號(hào)字符串前放置一個(gè)@符號(hào),,如下面的例子所示: NSString* myString = @"My String\n"; NSString* anotherString = [NSString stringWithFormat:@"%d %s", 1, @"String"]; // 從一個(gè)C語言字符串創(chuàng)建Objective-C字符串 NSString* fromCString = [NSString stringWithCString:"A C string" encoding:NSASCIIStringEncoding]; 類如同所有其他的面向?qū)ο笳Z言,,類是Objective-C用來封裝數(shù)據(jù),以及操作數(shù)據(jù)的行為的基礎(chǔ)結(jié)構(gòu),。對(duì)象就是類的運(yùn)行期間實(shí)例,,它包含了類聲明的實(shí)例變量自己的內(nèi)存拷貝,以及類成員的指針,。Objective-C的類規(guī)格說明包含了兩個(gè)部分:接口和實(shí)現(xiàn),。接口部分包含了類聲明和實(shí)例變量的定義,以及類相關(guān)的方法,。實(shí)現(xiàn)部分包含了類方法的實(shí)際代碼,。圖1展現(xiàn)了聲明一個(gè)叫做MyClass的類的語法,這個(gè)類繼承自NSObject基礎(chǔ)類,。類聲明總是由@interface編譯選項(xiàng)開始,,由@end編譯選項(xiàng)結(jié)束。類名之后的(用冒號(hào)分隔的)是父類的名字,。類的實(shí)例(或者成員)變量聲明在被大括號(hào)包含的代碼塊中,。實(shí)例變量塊后面就是類聲明的方法的列表。每個(gè)實(shí)例變量和方法聲明都以分號(hào)結(jié)尾,。 圖1 類聲明 列表1展現(xiàn)了前面例子中MyClass類的實(shí)現(xiàn),。類同與類聲明,類實(shí)現(xiàn)的位置也由兩個(gè)編譯選項(xiàng)確定,,@implementation和@end,。這些選項(xiàng)給編譯器提供了要將方法和對(duì)應(yīng)類聯(lián)系起來,所需的范圍信息,。因此方法的定義和接口中對(duì)應(yīng)的聲明是匹配的,,只是多了個(gè)代碼塊而已,。 列表1 類實(shí)現(xiàn) @implementation MyClass - (id)initWithString:(NSString *) aName { if (self = [super init]) { count count = 0; data = nil; name = [aName copy]; return self; } } + (MyClass *)createMyClassWithString: (NSString *) aName { return [[[self alloc] initWithString:aName] autorelease]; } @end注意: 雖然前面的類只聲明了方法,但是類可以聲明屬性,。想了解更多關(guān)于屬性的信息,,參看“屬性”。
當(dāng)用變量保存對(duì)象的時(shí)候,,始終應(yīng)該使用指針類型,。Objective-C對(duì)變量包含的對(duì)象支持強(qiáng)弱兩種類型。強(qiáng)類型指針的變量類型聲明包含了類名,。弱類型指針使用id作為對(duì)象的類型,。弱類型指針常用于類的集合,在集合中對(duì)象精確的類型可以是未知的,。如果你用過強(qiáng)類型語言,,你也許覺得使用弱類型變量可能會(huì)帶來問題,但是他們實(shí)際上給了Objective-C程序巨大的靈活性,,而且使它更強(qiáng)大,。 下面的例子里,展示了MyClass類的強(qiáng)類型和弱類型聲明變量: MyClass* myObject1; // Strong typing id myObject2; // Weak typing
方法Objective-C中的類可以聲明兩種類型的方法:實(shí)例方法和類方法,。實(shí)例方法就是一個(gè)方法,,它在類的一個(gè)具體實(shí)例的范圍內(nèi)執(zhí)行。也就是說,,在你調(diào)用一個(gè)實(shí)例方法前,,你必須首先創(chuàng)建類的一個(gè)實(shí)例。而類方法,,比較起來,,也就是說,,不需要你創(chuàng)建一個(gè)實(shí)例,。 方法聲明包括方法類型標(biāo)識(shí)符,返回值類型,,一個(gè)或多個(gè)方法標(biāo)識(shí)關(guān)鍵字,,參數(shù)類型和名信息。圖2展示insertObject:atIndex:實(shí)例方法的聲明,。聲明由一個(gè)減號(hào)(-)開始,,這表明這是一個(gè)實(shí)例方法。方法實(shí)際的名字(insertObject:atIndex:)是所有方法標(biāo)識(shí)關(guān)鍵的級(jí)聯(lián),,包含了冒號(hào),。冒號(hào)表明了參數(shù)的出現(xiàn)。如果方法沒有參數(shù),,你可以省略第一個(gè)(也是唯一的)方法標(biāo)識(shí)關(guān)鍵字后面的冒號(hào),。本例中,,這個(gè)方法有兩個(gè)參數(shù)。 圖2 方法聲明語法 當(dāng)你想調(diào)用一個(gè)方法,,你傳遞消息到對(duì)應(yīng)的對(duì)象,。這里消息就是方法標(biāo)識(shí)符,以及傳遞給方法的參數(shù)信息,。發(fā)送給對(duì)象的所有消息都會(huì)動(dòng)態(tài)分發(fā),,這樣有利于實(shí)現(xiàn)Objective-C類的多態(tài)行為。也就是說,,如果子類定義了跟父類的具有相同標(biāo)識(shí)符的方法,,那么子類首先收到消息,然后可以有選擇的把消息轉(zhuǎn)發(fā)(也可以不轉(zhuǎn)發(fā))給他的父類,。 消息被中括號(hào)( [ 和 ] )包括,。中括號(hào)中間,接收消息的對(duì)象在左邊,,消息(包括消息需要的任何參數(shù))在右邊,。例如,給myArray變量傳遞消息insertObject:atIndex:消息,,你需要使用如下的語法: [myArray insertObject:anObj atIndex:0];為了避免聲明過多的本地變量保存臨時(shí)結(jié)果,,Objective-C允許你使用嵌套消息。每個(gè)嵌套消息的返回值可以作為其他消息的參數(shù)或者目標(biāo),。例如,,你可以用任何獲取這種值的消息來代替前面例子里面的任何變量。所以,,如果你有另外一個(gè)對(duì)象叫做myAppObject擁有方法,,可以訪問數(shù)組對(duì)象,以及插入對(duì)象到一個(gè)數(shù)組,,你可以把前面的例子寫成如下的樣子: [[myAppObject getArray] insertObject:[myAppObject getObjectToInsert] atIndex:0];雖然前面的例子都是傳遞消息給某個(gè)類的實(shí)例,,但是你也可以傳遞消息給類本身。當(dāng)給類發(fā)消息,,你指定的方法必須被定義為類方法,,而不是實(shí)例方法。你可以認(rèn)為類方法跟C++類里面的靜態(tài)成員有點(diǎn)像(但是不是完全相同的),。
類方法的典型用途是用做創(chuàng)建新的類實(shí)例的工廠方法,,或者是訪問類相關(guān)的共享信息的途徑。類方法聲明的語法跟實(shí)例方法的幾乎完全一樣,,只有一點(diǎn)小差別,。與實(shí)例方法使用減號(hào)作為方法類型標(biāo)識(shí)符不同,類方法使用加號(hào)( + ),。 下面的例子演示了一個(gè)類方法如何作為類的工廠方法,。在這里,,arrayWithCapacity是NSMutableArray類的類方法,為類的新實(shí)例分配內(nèi)容并初始化,,然后返回給你,。 NSMutableArray* myArray = nil; // nil is essentially the same as NULL // Create a new array and assign it to the myArray variable. myArray = [NSMutableArray arrayWithCapacity:0]; 屬性屬性是用來代替聲明存取方法的便捷方式。屬性不會(huì)在你的類聲明中創(chuàng)建一個(gè)新的實(shí)例變量,。他們僅僅是定義方法訪問已有的實(shí)例變量的速記方式而已,。暴露實(shí)例變量的類,可以使用屬性記號(hào)代替getter和setter語法,。類還可以使用屬性暴露一些“虛擬”的實(shí)例變量,,他們是部分?jǐn)?shù)據(jù)動(dòng)態(tài)計(jì)算的結(jié)果,而不是確實(shí)保存在實(shí)例變量?jī)?nèi)的,。 實(shí)際上可以說,,屬性節(jié)約了你必須要些的大量多余的代碼。因?yàn)榇蠖鄶?shù)存取方法都是用類似的方式實(shí)現(xiàn)的,,屬性避免了為類暴露的每個(gè)實(shí)例變量提供不同的getter和setter的需求,。取而代之的是,你用屬性聲明指定你希望的行為,,然后在編譯期間合成基于聲明的實(shí)際的getter和setter方法,。 屬性聲明應(yīng)該放在類接口的方法聲明那里?;镜亩x使用@property編譯選項(xiàng),,緊跟著類型信息和屬性的名字。你還可以用定制選項(xiàng)對(duì)屬性進(jìn)行配置,,這決定了存取方法的行為,。下面的例子展示了一些簡(jiǎn)單的屬性聲明: @property BOOL flag; @property (copy) NSString* nameObject; // Copy the object during assignment. @property (readonly) UIView* rootView; // Create only a getter method.使用屬性另外的好處就是你可以在代碼中訪問他們的時(shí)候,使用點(diǎn)語法,,如下面的例子所示: myObject.flag = YES; CGRect viewFrame = myObject.rootView.frame;雖然前面例子里面的對(duì)象和屬性名是故意這么取的,,他們還是展現(xiàn)了屬性的靈活性。點(diǎn)語法實(shí)際上隱藏了對(duì)應(yīng)的方法調(diào)用,。每個(gè)可讀的屬性由一個(gè)與屬性同名的方法支持,。每個(gè)可寫屬性由一個(gè)叫做“set屬性名”的額外方法來支持,屬性名的第一個(gè)字母要大寫,。(這些方法是屬性的實(shí)際實(shí)現(xiàn)方式,也是你可以聲明一個(gè)沒有任何實(shí)例變量支持的屬性聲明的原因,。)如果用方法來代替前面代碼中的屬性,,你就要下下面的代碼: [myObject setFlag:YES]; CGRect viewFrame = [[myObject rootView] frame];要了解更多關(guān)于如何聲明屬性的信息,參看Objective-C 2.0編程語言的屬性一章,。
協(xié)議和代理協(xié)議聲明了可以被任何類實(shí)現(xiàn)的方法,。協(xié)議不是那些類本身,。他們僅是定義一個(gè)接口,其他的對(duì)象去負(fù)責(zé)實(shí)現(xiàn),。你實(shí)現(xiàn)了協(xié)議里面的方法,,就叫做符合協(xié)議。 在iPhone OS中協(xié)議常用來實(shí)現(xiàn)委托對(duì)象,。委托對(duì)象就是一個(gè)對(duì)象以其他的對(duì)象的模式行事,。了解協(xié)議,委托和對(duì)象最好的辦法就是看一個(gè)例子,。 UIApplication類實(shí)現(xiàn)了一個(gè)程序需要的行為,。如果想接收程序當(dāng)前狀態(tài)的簡(jiǎn)單消息,并不需要強(qiáng)制你創(chuàng)建UIApplication的一個(gè)子類,,反之UIApplication類通過調(diào)用委托對(duì)象的指定方法來分發(fā)這些通知消息,。實(shí)現(xiàn)UIApplicationDelegate方法的對(duì)象都可以接受這樣的通知,并進(jìn)行響應(yīng)的反應(yīng),。 協(xié)議的聲明跟類接口的聲明很像,,只是協(xié)議沒有父類,而且他們不會(huì)定義任何實(shí)例變量,。下面的例子展示了一個(gè)有一個(gè)方法的協(xié)議聲明: @protocol MyProtocol - (void)myProtocolMethod; @end在大多數(shù)委托協(xié)議情況下,,使用某種協(xié)議僅僅是簡(jiǎn)單的實(shí)現(xiàn)協(xié)議定義的方法而已。 有些協(xié)議要求你明確的表明你支持這種協(xié)議,,協(xié)議可以指定必須或者可選的方法,。在你深入開發(fā)的過程中,你應(yīng)該花點(diǎn)時(shí)間學(xué)習(xí)協(xié)議以及他們的用途,,請(qǐng)閱讀Objective-C 2.0編程語言的協(xié)議章節(jié),。
更多的信息前面的信息是為了讓你對(duì)Objective-C語言的基礎(chǔ)所有了解。本文提到的語言特性,,你可以在閱讀完整文檔的時(shí)候找到,。但是這個(gè)語言不僅僅有這些特性,所以最好請(qǐng)仔細(xì)閱讀文檔Objective-C 2.0編程語言,。 |
|