定义类
面向对象的程序设计过程中有两个重要概念:类(class)和对象(object)其中类是某一批对象的抽象,可以把类理解成某种概念;而对象才是一个具体的实例。
Objective-C中定义类需要分为两个步骤。
- 接口部分:定义该类包含的成员变量和方法。
- 实现部分:为该类的方法提供实现。
定义接口部分实例:
@interface MyClass : NSObject {
//成员变量
int _count;
id _data;
NSString* _Name;
}
//方法
- (void)initWithString:(NSString*)aName;
+ (MyClass*)createMyClassWithString:(NSString*)aName;
@end
对于面向对象编程来说,成员变量和方法都是非常重要的概念,其中
- 成员变量:用于描述该类的对象的状态数据。
- 方法:用于描述该类的行为。
一般来说,我们会将定义类的借口声明部分放在头文件(*.h)中。
定义成员变量的语法格式如下:
类型 成员变量名;
其中
- 类型:可以是Objective-C语言允许的任何数据类型。
- 成员变量名:从语法角度来说,成员变量名只要是一个合法的标识即可。
声明方法的语法格式如下:
-(void)insertObject atIndex:(NUSInteger)index
说明:
- 方法标识类型:该标识要么是+,要么是-,其中,+代表该方法是类方法,直接用类名即可调用;-代表该方法是实例方法,必须用对象才能调用。
- 方法返回值类型:返回值类型可以是Objective-C允许的任何数据类型。
- 方法签名关键字:Objective-C的方法签名关键字由方法名、形参标签和冒号组成。
Objective-C的方法声明中,所有的类型都应该使用圆括号括起来。
除了接口部分之外,Objective-C的类还需要定义实现部分,定义实现部分语法格式如下:
@implementation MyClass {
//成员变量
}
- (id)initEithString:(NSString*)aName {
// 方法体
}
+ (MyClass*)createMyClassWithString:(NSString *)aName {
// 方法体
}
@end
关于类实现部分说明:
- 类实现部分的类名必须与类接口部分的类名相同,用于表示这是同一个类的接口部分和实现部分。
- 类实现部分也可以声明自己的成员变量,但这些成员变量只能在当前类内访问
- 类实现部分必须为类声明部分每个方法提供方法定义。也可以提供附加的方法定义,这些方法只能在类内使用。
对象的产生和使用
定义类后就可以使用类。
定义变量的语法为:
类名* 变量名;
创建对象的语法为:
[[类名 alloc] 初始化方法];
alloc是Objective-C的关键字,负责为该类分配内存空间,创建对象。所有的类都有一个默认的初始化方法:init。
调用方法的语法为:
[调用者 方法名:参数 形参标签:参数值 …];
如果方法中声明了多个形参,那么调用该方法时需要为每个形参传入参数值。
对象和指针
我们先来看一行代码
MyClass* person = [[MyClass alloc] init];
这行代码实际上产生了两个东西:person变量和MyClass对象。
- person变量:本质是一个指针变量,仅仅保存了MyClass对象在内存中的首地址。
- MyClass对象:保存在堆内存中,Objective-C不允许直接访问堆内存中的对象,只能通过该对象的指针变量来访问该对象。
如果堆内存里的对象没有任何变量指向该变量,Objective-C要求程序员释放该对象所占用的内存。
self关键字
Objective-C提供了一个self关键字,self关键字总是指向调用该方法的对象。
self关键字的最大作用是让类中的一个方法访问该类的另一个方法或成员变量。
请看下程序:
#import <Foundation/Foundation.h>
@interface FKDog : NSObject
//定义一个jump方法
- (void) jump;
//定义一个run方法
- (void) run;
@end
@implementation FKDog
//实现一个jump方法
- (void) jump {
NSLog(@"正在执行jump方法\n");
}
- (void) run {
//使用self访问jump方法
[self jump];
NSLog(@"正在执行run方法\n");
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
FKDog* dog;
dog = [[FKDog alloc] init];
[dog jump];
[dog run];
}
return 0;
}
运行结果:
2022-05-06 11:45:23.816869+0800 oc.programme[12201:383987] 正在执行jump方法
2022-05-06 11:45:23.817085+0800 oc.programme[12201:383987] 正在执行jump方法
2022-05-06 11:45:23.817106+0800 oc.programme[12201:383987] 正在执行run方法
Program ended with exit code: 0
在上例中dog对象中的run方法通过self关键字访问了jump方法。
id类型
Objective-C提供了一个id类型,这个id类型可以代表所有对象类型。也就是说,任意类的对象都可赋值给id类型的变量。
当通过id类型的变量来调用方法时,Objective-C将会跟踪对象所属的类,它会在运行时判断对象所属的类,并在运行时确定需要调用的方法。
我们可以尝试将上例中main函数内的FKDog* dog
改成id dog
查看运行结果。
#import <Foundation/Foundation.h>
@interface FKDog : NSObject
//定义一个jump方法
- (void) jump;
//定义一个run方法
- (void) run;
@end
@implementation FKDog
//实现一个jump方法
- (void) jump {
NSLog(@"正在执行jump方法\n");
}
- (void) run {
//使用self访问jump方法
[self jump];
NSLog(@"正在执行run方法\n");
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
id dog; //尝试使用id类型
dog = [[FKDog alloc] init];
[dog jump];
[dog run];
}
return 0;
}
运行结果:
2022-05-08 18:56:42.967775+0800 oc.programme[17339:618449] 正在执行jump方法
2022-05-08 18:56:42.968266+0800 oc.programme[17339:618449] 正在执行jump方法
2022-05-08 18:56:42.968286+0800 oc.programme[17339:618449] 正在执行run方法
Program ended with exit code: 0