Objective-C是一種簡單的計算機語言,設計為可以支援真正的面向對象程式設計。Objective-C通過提供類定義,方法以及屬性的文法,還有其他可以提高類的動态擴充能力的結構等,擴充了标準的ANSI C語言。類的文法和設計主要是基于Smalltalk,最早的面向對象程式設計語言之一。
如果你以前使用過其他面向對象程式設計語言,那麼下面的資訊可以幫助你學習Objective-C的基本文法。許多傳統的面向對象概念,例如封裝,繼承以及多态,在Objective-C中都有所展現。這裡有一些重要的不同,但是這些不同在這文章會表現出來,而且如果你需要還有更多詳細的資訊存在。
如果你從來沒有使用任何程式設計語言編過上海闵行企業網站制作程式,那麼你至少需要在開始之前,對相關概念進行一些基礎的了解。對象的使用和對象對象架構是iPhone程式設計的基礎,了解他們如何互動對建立你的程式非常重要。想了解面向對象概念的,請參看使用Objective-C進行面向對象程式設計。此外,參看Cocoa基礎指南可以獲得Cocoa中的面向對象設計模式的資訊。
Objective-C: C的超集
Objective-C是ANSI版本C程式設計語言的超集,支援C的基本文法。在C代碼中,你定義頭檔案和源代碼檔案,從代碼實作細節分離公共聲明。Objective-C頭檔案使用的檔案名列在表1中。
表1 Objective-C代碼的檔案擴充名
擴充名 | 内容類型 |
.h | 上海闵行企業網站設計與制作dercolor="#000000">頭檔案。頭檔案包含類,類型,函數和常數的聲明。 |
.m | 源代碼檔案。這是典型的源代碼檔案擴充名,可以包含Objective-C和C代碼。 |
.mm | 源代碼檔案。帶有這種擴充名的源代碼檔案,除了可以包含Objective-C和C代碼以外還可以包含C++代碼。僅在你的Objective-C代碼中确實需要使用C++類或上海徐彙企業網站制作者特性的時候才用這種擴充名。 |
當你需要在源代碼中包含頭檔案的時候,你可以使用标準的#include編譯選項,但是Objective-C提供了更好的方法。#import選項和#include選項完全相同,隻是它可以確定相同的檔案隻會被包含一次。Objective-C的例子和文檔都傾向于使用#import,你的代碼也應該是這樣的。
字元串
作為C語言的超集,Objective-C支援C語言字元串方面的約定。也就是說,單個字元被單引号包括,字元串被雙引号包括。然而,大多數Objective-C通常不使用C語言風格的字元串。反之,大多數架構把字元串傳遞給NSString對象。NSString類提供了字元串的類包裝,包含了所有你期望的優點,包括對儲存任意長度字元串的内建記憶體管理機制,支援Unicode,printf風格的格式化工具,等等。因為這種字元串使用的非常頻繁,Objective-C提供了一個助記符可以友善地從常量值建立NSString對象。要使用這個助記符,你需要做的全部事情,是在普通的雙引号字元串前放置一個@符号,如下面的例子所示:
NSString* myString = @"My String\n";
NSString*上海網站建設tyle="color: #000000;"> anotherString = [NSString stringWithFormat:@"%d %s", 1, @"String"];
// 從一個C語言字元串建立Objective-C字元串
NSString* fromCString = [NSString stringWithCString:"A C string"
encoding:NSASCIIStringEncoding];
類
如同所有其他的面向對象語言,類是Objective-C用來封裝資料,以及操作資料的行為的基礎結構。對象就是類的運作期間執行個體,它包含了類聲明的執行個體變量自己的記憶體拷貝,以及類成員的指針。Objective-C的類規格說明包含了兩個部分:接口和實作。接口部分包含了類聲明和執行個體變量的定義,以及類相關的方法。實作部分包含了類方法的實際代碼。圖1展現了聲明一個叫做MyClass的類的文法,這個類繼承自NSObject基礎類。類聲明總是由@interface編譯選項開始,由@end編譯選項結束。類名之後的(用冒号分隔的)是父類的名字。類的執行個體(或者成員)變量聲明在被大括号包含的代碼塊中。執行個體變量塊後面就是類聲明的方法的清單。每個執行個體變量和方法聲明都以分号結尾。
圖1 類聲明
清單1展現了前面例子中MyClass類的實作。類同與類聲明,類實作的位置也由兩個編譯選項确定,@implementation和@end。這些選項給編譯器提供了要将方法和對應類聯系起來,所需的範圍資訊。是以方法的定義和接口中對應的聲明是比對的,隻是多了個代碼塊而已。
清單1 類實作
@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
注意: 雖然前面的類隻聲明了方法,但是類可以聲明屬性。
當用變量儲存對象的時候,始終應該使用指針類型。Objective-C對變量包含的對象支援強弱兩種類型。強類型指針的變量類型聲明包含了類名。弱類型指針使用id作為對象的類型。弱類型指針常用于類的集合,在集合中對象精确的類型可以是未知的。如果你用過強類型語言,你也許覺得使用弱類型變量可能會帶來問題,但是他們實際上給了Objective-C程式巨大的靈活性,而且使它更強大。
下面的例子裡,展示了MyClass類的強類型和弱類型聲明變量:
MyClass* myObject1; // Strong typing
id myObject2; // Weak typing
方法
Objective-C中的類可以聲明兩種類型的方法:執行個體方法和類方法。執行個體方法就是一個方法,它在類的一個具體執行個體的範圍内執行。也就是說,在你調用一個執行個體方法前,你必須首先建立類的一個執行個體。而類方法,比較起來,也就是說,不需要你建立一個執行個體。
方法聲明包括方法類型辨別符,傳回值類型,一個或多個方法辨別關鍵字,參數類型和名資訊。圖2展示insertObject:atIndex:執行個體方法的聲明。聲明由一個減号(-)開始,這表明這是一個執行個體方法。方法實際的名字(insertObject:atIndex:)是所有方法辨別關鍵的級聯,包含了冒号。冒号表明了參數的出現。如果方法沒有參數,你可以省略第一個(也是唯一的)方法辨別關鍵字後面的冒号。本例中,這個方法有兩個參數。
圖2 方法聲明文法
當你想調用一個方法,你傳遞消息到對應的對象。這裡消息就是方法辨別符,以及傳遞給方法的參數資訊。發送給對象的所有消息都會動态分發,這樣有利于實作Objective-C類的多态行為。也就是說,如果子類定義了跟父類的具有相同辨別符的方法,那麼子類首先收到消息,然後可以有選擇的把消息轉發(也可以不轉發)給他的父類。
消息被中括号( [ 和 ] )包括。中括号中間,接收消息的對象在左邊,消息(包括消息需要的任何參數)在右邊。例如,給myArray變量傳遞消息insertObject:atIndex:消息,你需要使用如下的文法:
[myArray insertObject:anObj atIndex:0];
為了避免聲明過多的本地變量儲存臨時結果,Objective-C允許你使用嵌套消息。每個嵌套消息的傳回值可以作為其他消息的參數或者目标。例如,你可以用任何擷取這種值的消息來代替前面例子裡面的任何變量。是以,如果你有另外一個對象叫做myAppObject擁有方法,可以通路數組對象,以及插入對象到一個數組,你可以把前面的例子寫成如下的樣子:
[[myAppObject getArray] insertObject:[myAppObject getObjectToInsert] atIndex:0];
雖然前面的例子都是傳遞消息給某個類的執行個體,但是你也可以傳遞消息給類本身。當給類發消息,你指定的方法必須被定義為類方法,而不是執行個體方法。你可以認為類方法跟C++類裡面的靜态成員有點像(但是不是完全相同的)。
類方法的典型用途是用做建立新的類執行個體的工廠方法,或者是通路類相關的共享資訊的途徑。類方法聲明的文法跟執行個體方法的幾乎完全一樣,隻有一點小差别。與執行個體方法使用減号作為方法類型辨別符不同,類方法使用加号( + )。
下面的例子示範了一個類方法如何作為類的工廠方法。在這裡,arrayWithCapacity是NSMutableArray類的類方法,為類的新執行個體配置設定内容并初始化,然後傳回給你。
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];
屬性
屬性是用來代替聲明存取方法的便捷方式。屬性不會在你的類聲明中建立一個新的執行個體變量。他們僅僅是定義方法通路已有的執行個體變量的速記方式而已。暴露執行個體變量的類,可以使用屬性記号代替getter和setter文法。類還可以使用屬性暴露一些“虛拟”的執行個體變量,他們是部分資料動态計算的結果,而不是确實儲存在執行個體變量内的。
實際上可以說,屬性節約了你必須要寫的大量多餘的代碼。因為大多數存取方法都是用類似的方式實作的,屬性避免了為類暴露的每個執行個體變量提供不同的getter和setter的需求。取而代之的是,你用屬性聲明指定你希望的行為,然後在編譯期間合成基于聲明的實際的getter和setter方法。
屬性聲明應該放在類接口的方法聲明那裡。基本的定義使用@property編譯選項,緊跟着類型資訊和屬性的名字。你還可以用定制選項對屬性進行配置,這決定了存取方法的行為。下面的例子展示了一些簡單的屬性聲明:
@property BOOL flag;
@property (copy) NSString* nameObject; // Copy the object during assignment.
@property (readonly) UIView* rootView; // Create only a getter method.
使用屬性另上海企業網站制作外的好處就是你可以在代碼中通路他們的時候,使用點文法,如下面的例子所示:
myObject.flag = YES;
CGRect viewFrame = myObject.rootView.frame;
雖然前面例子裡面的對象和屬性名是故意這麼取的,他們還是展現了屬性的靈活性。點文法實際上隐藏了對應的方法調用。每個可讀的屬性由一個與屬性同名的方法支援。每個可寫屬性由一個叫做“set屬性名”的額外方法來支援,屬性名的第一個字母要大寫。(這些方法是屬性的實際實作方式,也是你可以聲明一個沒有任何執行個體變量支援的屬性聲明的原因。)如果用方法來代替前面代碼中的屬性,你就要下下面的代碼:
[myObject setFlag:YES];
CGRect viewFrame = [[myObject rootView] frame];
協定和代理
協定聲明了可以被任何類實作的方法。協定不是那些類本身。他們僅是定義一個接口,其他的對象去負責實作。你實作了協定裡面的方法,就叫做符合協定。
在iPhone OS中協定常用來實作委托對象。委托對象就是一個對象以其他的對象的模式行事。了解協定,委托和對象最好的辦法就是看一個例子。
UIApplication類實作了一個程式需要的行為。如果想接收程式目前狀态的簡單消息,并不需要強制你建立UIApplication的一個子類,反之UIApplication類通過調用委托對象的指定方法來分發這些通知消息。實作UIApplicationDelegate方法的對象都可以接受這樣的通知,并進行響應的反應。
協定的聲明跟類接口的聲明很像,隻是協定沒有父類,而且他們不會定義任何執行個體變量。下面的例子展示了一個有一個方法的協定聲明:
@protocol MyProtocol
- (void)myProtocolMethod;
@end