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 的具体信息。