學習Objective-C: 入門教材
Objective-C是一種簡單的計算機語言,它可以用來設計複雜的面向對象程序。Objective-C擴展了標準ANSI C語言,增加了一些定義類、方法以及其它結構的語法,提升了類的動態擴展。
重點: 本文檔沒有教授任何有關於C語言的知識。如果你還不熟悉C語言,閱讀本文之前應該學習一下C語言的基礎知識。
閱讀本文前,你也要了解面向對象的基本概念。對象的使用以及面象對象設計模式都是設計Cocoa程序的基礎,理解它們是如何相互影響的是編寫你的應用的關鍵。瞭解這些概念,請查看 使用Objective-C進行面向對象編程。另外, 查看 Cocoa基本原理入門 可以瞭解有關在Cocoa中用到的設計模式
如果你已經熟悉C語言,並且之前使用過面嚮對象語言編寫過程序,下面的內容將會幫助你學習Objective-C的基礎語法。許多傳統面向對象的思想,比如封裝、繼承、多態,都會在Objective-C中體現。雖然也有一些重要的不同點,但這些不同點都會在這篇文章中提到,如果需要有更多詳細信息可用。
有關Objective-C的語言和語法的詳細信息, 可以查閱 Objective-C編程語言.
[來自三聰博客]
目錄:
Objective-C: C語言的超集
類庫
方法和通信
聲明屬性
字符串
協議
更多信息
" src="/CuteSoft_Client/CuteEditor/Images/anchor.gif">
Objective-C: C語言的超集
Objective-C是C語言ANSI版本的超集,支持和C相同的基本語法。用C代碼,你可以定義頭文件和源碼文件,以從詳細實現的代碼中分離出公開的聲明。Objective-C頭文件下面列出的擴展名 Table1-1.
" src="/CuteSoft_Client/CuteEditor/Images/anchor.gif">
擴展名 |
文件類型 |
---|---|
|
頭文件。頭文件包含類、類型、函數、常量的聲明。 |
|
源碼文件。這是源碼文件的典型擴展名,可以包含Objective-C和C代碼。 |
|
源碼文件。使用該擴展名的源文件除了Objective-C和C代碼,還可以包含C++代碼。 該擴展名僅用於在你的Objective-C代碼中引用到的C++類和特性。 |
當你想在你的代碼中包含頭文件時,你可以使用 #import
指令。 它比較像 #include
,除了它必須要確定相同文件不能被包含多次。Objective-C的示例和文檔都更喜歡使用 #import
,你的代碼應該也這樣。
類
和大多數其它面嚮對象語言一樣,Objective-C裏的類也提供基本的結構,用來封裝帶有行爲的一些數據。一個對象是一個類的運行實例,包含類中聲明變量的實例在內存中的複製,以及指向該類的方法。
Objective-C中類的定義,要求兩個明顯的部分:接口和實現。接口部分包含類的聲明、定義成員變量,及與此類關聯的方法。接口通常在a .h
文件裏。實現部分包含類的方法實際代碼。實現通常在a .m
文件裏。
圖1-1 展示聲明MyClass
類的語法,它繼承自Cocoa的基類 NSObject
。這個類的聲明開始於 @interface
編譯指令,結束於 @end
指令。僅跟着類名的(以冒號分割)是父類名。類的實體變量(有時簡稱ivars,在一些其它語言中稱作成員變量)聲明在以大括號({和})括起來的代碼塊中。實體變量後面是類的方法聲明列表。以分號做爲每個實體變量和方法的結束標記。
小提示: 這個接口只聲明瞭方法,類也可以聲明 屬性。瞭解屬性的更多信息, 請查看 “聲明屬性”.
Objective-C支持包含對象的強弱兩個類型的變量。在變量聲明時,強類型的變量包含類名,弱類型的變量使用類型 id
代替對象。弱類型變量在像集合類中使用頻繁,在一個集合中的對象的實際類型可能是未知的。如果你使用過強類型的語言,你可能會認爲使用弱類型會引起問題,但是在Objective-C程序中它們實際上提供了很大的靈活性和更強大的動態性。
下面的例子展示了強類型和弱類型變量的聲明格式:
MyClass *myObject1; // 強類型 |
id myObject2; // 弱類型 |
注意在第一個聲明裏的 *
號。在Objective-C中,對象的引用叫指針。如果你對指針沒有很清晰的認識,不用擔心,不是必須要成爲一個指針專家才能使用Objective-C進行編程的。你只要記住在聲明強類型對象的變量名前加上 *
就可以了。
弱類型 id
本身就意味着是個指針。
方法和通信
Objective-C中的類可以聲明兩種類型的方法:實體方法和類方法。一個實體方法是在這個特定類的實例中才能執行的方法,換句話說,在調用實體方法前,你必須首先要創建這個類的實例。類方法,相對的,不需要創建實例。當然更可以在創建實例之後調用。
方法的聲明由方法的類型標識符、一個返回值類型、一個或多個簽名關鍵字、參數類型和名稱信息組成。 圖1-2 展示實體方法 insertObject:atIndex:
的聲明格式。
聲明開始於減號(-
),減號用來標識這是一個實體方法。這個方法的實際名稱(insertObject:atIndex:
) 是所有簽名關鍵字的拼接,包括冒號。冒號聲明瞭當前的參數.如果方法沒有參數,你就可以省略第一個簽名關鍵字。在這個例子中,該方法有兩個參數。
當你想調用這個方法時,你可以通過向對象 通信 。 通信內容是方法簽名和方法要求參數信息。
信息是用中括號 ([
和 ]
)包裹的。在中括號裏面,接收信息的對象在左邊,信息(包括信息要求的參數)在右邊。例如,發送信息insertObject:atIndex:
到變量名爲 myArray
的對象,你會用到下面的語法:
[myArray insertObject:anObject atIndex:0]; |
爲了避免聲明多個局部變量來保存臨時結果,Objective-C允許你嵌套信息。來自每個嵌套信息中的返回值,可以被用做參數、目標、或另一個信息。例如,你可以用信息來代替前面例子中任意使用過的變量。從而,如果你有一個叫 myAppObject
的對象,它有訪問數組對象和將對象插入數組的方法,你可以將前面的例子寫成像下面這樣:
[[myAppObject theArray] insertObject:[myAppObject objectToInsert] atIndex:0]; |
Objective-C也提供用句點來調用 存取器方法。存取器方法獲取和設置一個對象的狀態,典型的格式爲 -(type)
propertyName 和 -(void)set
PropertyName:(type)
。使用句點語法,你可以將前面的例子重寫成:
[myAppObject.theArray insertObject:[myAppObject objectToInsert] atIndex:0]; |
你也能使用句點語法賦值:
myAppObject.theArray = aNewArray; |
用不同語法寫也比較簡單, [myAppObjectsetTheArray:aNewArray];
.
儘管前面的例子都是發送信息給一個類的實例,你也可以發送信息到類本身。當你要通信到一個類,你指定的方法必須被定義成一個類方法,而非實體方法。
典型的,你使用類方法來創建類的新實例,或訪問有關此類的一些共享信息。類方法的聲明語法除了一點不同,其它完全和實體方法一樣。用加號(+)來代替用減號(-)作爲方法類型的標識符。
下面的例子就是來說明如何使用類方法作爲一個類的工廠方法。在這個例子中,方法 array
是類 NSArray
的類方法—繼承自 NSMutableArray
—它用於分配和初始化該類的新實例並將它的返回到代碼中。
NSMutableArray *myArray = nil; // nil等同NULL |
|
// 創建一些新數組並賦給變量myArray。 |
myArray = [NSMutableArray array]; |
清單1-1 展示類了在前面例子中 MyClass
類的實現代碼。像類的聲明一樣,類的實現通過兩個編譯指令識別—這裏, @implementation
和 @end
。這些指令提供編譯器需要的範圍信息,來定位相對應類的封閉方法。方法的聲明要匹配接口中相應的聲明,不包括代碼塊裏的內容。
清單1-1 一個類的實現
@implementation MyClass |
|
- (id)initWithString:(NSString *)aName |
{ |
self = [super init]; |
if (self) { |
name = [aName copy]; |
} |
return self; |
} |
|
+ (MyClass *)createMyClassWithString: (NSString *)aName |
{ |
return [[[self alloc] initWithString:aName] autorelease]; |
} |
@end |
聲明屬性
聲明屬性是代替聲明及簡單實現存取器方法的方便形式。
在類接口裏,可以包含屬性聲明和方法聲明。基本的定義用 @property
編譯指令,之後是類型信息和屬性名稱。你也可以定製配置屬性,比如定義存取器方法如何執行。下面的例子展示一個簡單屬性的聲明:
@property BOOL flag; |
@property (copy) NSString *nameObject; // 在賦值時複製對象。 |
@property (readonly) UIView *rootView; //聲明一個只讀方法 |
每個可讀屬性指定一個與該屬性同名的方法。每個可寫屬性指定一個額外的方法,格式爲 set
PropertyName,屬性名的首字母要大寫。
在你的類的實現裏,你可以使用 @synthesize
編譯指令來要求編譯器依照聲明規格創建方法:
@synthesize flag; |
@synthesize nameObject; |
@synthesize rootView; |
你可以合併 @synthesize
語句到一行中,如果你願意:
@synthesize flag, nameObject, rootView; |
從實際上說,屬性減少了你不得不寫的冗長代碼的數量。因爲大多數存取器方法都是以類似的方式執行的,屬性去掉了類中公開的每個屬性實現讀寫方法的重複。相反的,你只要指定你想使用屬性的行爲,會在編譯時生成實際的讀寫方法。
要了解如何在你的類中聲明屬性,請查看 “聲明屬性” 在 Objective-C編程語言裏。
字符串
作爲C語言的超集,Objective-C和C語言一樣在指定字符串上支持相同的約定。換句話說,字符用單引號包裹、字符串用雙引號包裹。可是Objective-C框架典型的是不使用C語言式的字符串。他們以 NSString
對象的方式傳遞字符串。
NSString
類提供一個對象封裝字符串,這樣可以具有你想要的所有優點,包括爲任意長度的字符串創建內存管理、支持Unicode、 printf
-式的格式化工具集,還有更多。因爲這樣的字符串使用很普遍,Objective-C提供一個快捷方式來根據常量創建 NSString
對象.
要使用這種快捷方式,你必須在普通雙引號字符串前加 @
符號,下面的例子就做了展示:
NSString *myString = @"My String\n"; |
NSString *anotherString = [NSString stringWithFormat:@"%d %@", 1, @"String"]; |
|
// 根據C式字符串創建Objective-C字符趾 |
NSString *fromCString = [NSString stringWithCString:"A C string" encoding:NSASCIIStringEncoding]; |
協議
一個協議聲明的方法可以被任意類實現。協議本身沒有類。他們只是簡單地定義一個接口讓其它對象可靠的實現。當你在你的類裏實現一個協議的方法時,就可以說你的類符合那個協議了。
協議被頻繁用於爲 委拖 對象指定接口。看協議、委託以及其它對象之間的相互作用的最好方式,就是看一個例子。
UIApplication
類實現一個應用程序要求的行爲。不用強迫你實現子類 UIApplication
來接收有當前程序狀態的簡單通知。而是 UIApplication
類通過調用它分配的委託對象的具體方法來發送那些通知。實現 UIApplicationDelegate
協議方法的對象能接收那些通知,並提供恰當的答覆。通過將協議的名稱用“<>”包裹起來放到它繼承的類後面,來指定你的類遵循或採用的協議。你不用去聲明你實現協議的方法。
@interface MyClass : NSObject <UIApplicationDelegate, AnotherProtocol> { |
} |
@end |
協議的聲明看起來比較類似一個類的接口,不同的是協議沒有父類也不能定義實體變量。下面的例子展示了含有一個方法的簡單協議:
@protocol MyProtocol |
- (void)myProtocolMethod; |
@end |
在很多委託協議的示例中,採用一個協議類似實現協議中定義的方法。有些協議要求你明確說明你支持的協議,協議可以指定必選和可選方法。當你要將你的開發推進到更深層次,無論如何,你應該花稍多時間去學習協議及如何使用它們-- “協議” in Objective-C編程語言.
" src="/CuteSoft_Client/CuteEditor/Images/anchor.gif">更多信息
上述內容主要是想讓你熟悉Objective-C語言的基礎。這裏介紹的主題覆蓋了你通讀文檔時最可能遇到的語言功能。這些內容不是這門語言的僅有功能,我們鼓勵你閱讀有關這門語言的更多內容-- Objective-C編程語言.