Cocoa 程式設計/Objective-C 基礎
Objective-C 是 Cocoa 應用程式的原生語言。它是 ANSI C 的面向物件超集,允許開發人員在程式中包含“純 C”語句和程式碼。任何 ANSI C 程式都是有效的 Objective-C 程式。
Cocoa 中使用的 Objective-C 與“純”Objective-C 有些不同,因為 Cocoa 執行時系統定義了一個新的根類,NSObject。所有 Cocoa 物件都應該是 NSObject 的後代,以便從其改進的記憶體管理模型中獲益。
NSObject 在標頭檔案 <Foundation/NSObject.h> 中定義。
要建立一個 NSObject,向其類傳送 alloc 或 new 訊息
id anObject = [NSObject new]; // Creates and returns an initialized object
id anotherObj = [NSObject alloc]; // Not yet ready for use...
anotherObj = [anotherObj init]; //...now it is.
// good style: combine alloc and init:
id oneMoreObj = [[NSObject alloc] init]; // identical to using new
儘管“new”和“alloc 後跟 init”方法看起來相同,但 Apple 文件似乎更喜歡後一種方法。這使開發人員能夠分別覆蓋 alloc 或 init 以實現特定結果(如果需要)。
請注意,初始化物件有時可能會失敗:例如,包含初始化資料的檔案可能不可用。在這種情況下,init 將返回 nil。因此,在使用物件之前始終檢查 init 的返回值!
物件初始化後,就可以使用了。要使用物件,向其傳送訊息
[anObject aMessage];
如果物件理解該訊息,它將對其做出反應。否則,將生成一個陷阱。
當不再使用物件時,必須將其釋放。要釋放物件,向其傳送 release 訊息。
[anObject release];
這將導致物件的銷燬(除非它仍在其他地方使用,請參閱Cocoa 記憶體管理瞭解詳細資訊)。
當物件即將被銷燬時,它將收到 dealloc 訊息。如果物件保留了任何資源,現在應該釋放它們。
Cocoa/Objective-C 應用程式中的所有類都應該是 NSObject 的派生類。因此,在定義新類時,您應該遵循一些基本規則
- 從
NSObject派生 - 直接或從派生類派生
- 定義初始化器和析構器
- 呼叫基類初始化器和析構器
要將您的類建立為 NSObject 的子類,請按如下方式定義它(在介面定義檔案“MyClass.h”中)
#import <Foundation/NSObject.h>
@interface MyClass : NSObject
{
@private
/* instance variable declarations */
AnotherClass* myMember;
}
/* method declarations */
@end
初始化器是初始化物件的方法。在 Cocoa 中,NSObject 的初始化器稱為 init。NSObject 的 init 方法不知道使用者定義的類,因此無法正確初始化它們的例項。因此,必須為您的類編寫一個初始化器方法。如果初始化不需要任何引數,則要定義的方法稱為 init(即,您應該覆蓋基類初始化器)。這使得可以使用從 NSObject 派生的 new 類方法建立您的類的例項
MyClass* myObj = [[MyClass alloc] init]; // allocate and initialize the object
上面的程式碼建立了一個新的 MyClass 例項。由於 MyClass 沒有名為 alloc 或 init 的方法,因此訊息會自動傳送到其基類。
要覆蓋您的類的初始化器,可以選擇在介面檔案中定義它
/* In MyObject.h, in the method declarations part */
- (id) init;
並在.m 檔案中實現它
/* In MyObject.m */
@implementation MyObject
- (id) init
{
/* first initialize the base class */
self = [super init];
/* then initialize the instance variables */
myMember = [AnotherClass new];
/* finally return the object */
return self;
}
@end
如果初始化需要其他引數,您應該定義一個類似 initWithParam: 的初始化器,例如
- (id) initWithMember: (AnotherClass) member
{
self = [super init];
myMember = [[AnotherClass alloc] initWithValue: member];
return self;
}
即使這樣,也建議定義一個“預設”初始化器,它使用合適的預設引數呼叫您的 initWithXXX 方法
- (id) init
{
return [self initWithMember: someDefaultValue];
}
析構器是一個負責釋放物件持有的所有資源的方法。析構器在釋放物件之前被呼叫,從而確保一切被正確清理。在 Cocoa 中,析構器方法是 dealloc。每個持有任何資源的類都應該定義一個 dealloc 方法。例如
- (void) dealloc
{
[myMember release];
[super dealloc];
}
當一個類從另一個類派生(例如,MyClass 從 NSObject 派生)時,從它建立的例項不僅是派生類的例項,也是基類的例項。這稱為is-a 關係。派生類是基類的擴充套件:它可以做基類不能做的事情,但它可以做基類能做的一切。因此,派生類的物件總是包含基類物件包含的一切。如果 NSObject 包含一個保留計數成員變數,那麼 MyClass 物件也會包含它。因此,在初始化和銷燬派生物件時,需要初始化和銷燬派生物件的“基類部分”。
要初始化物件的基類部分,請編寫
self = [super init];
到您的類的初始化器的開頭。要銷燬物件的基類部分,請編寫
[super dealloc];
到您的類的析構器的結尾。
有關 Cocoa 中 Objective-C 的更多資訊,請參閱
- Objective-C 程式設計,瞭解有關 Objective-C 的一般資訊
- Objective-C GNUstep Base 程式設計手冊,瞭解有關 Cocoa/GNUstep 中 Objective-C 的具體資訊。