为什么不经常说创建一个类呢?
因为类其实是变量和行为操作整合在一起的一套规则,是虚幻的没有实际意义的,比如“学生”。但是我利用这个规则(学生)创建一个对象叫小明,这就是实实在在的根据类的规则创建出的对象,所以我们一般把类叫做声明,把对象叫做创建。
我们在xcode里面可以 New File >>> Objective-C class来新建一个,这里面填写的名称就是类名称,一般有个短前缀+类名首字母大写,比如ASStudent,AS是短前缀。
我们一般声明类都是从根类继承过来声明,因为根类里面已经给我们封装了内存分配、内存回收、对象初始化、对象描述等等,如果你不继承根类而是自己直接声明的话,要写很多东西。这里面的根类是NSObject。
点击确定后,我们发现有两个已经创建好的文件,一个是ASStudent.h(头文件),一个是ASStudent.m(OC文件)。
- 我们在ASStudent.h(头文件)里面声明这个类:包括变量和方法的定义(就是一些不同于我们常见的一种函数定义)
- 在ASStudent.m里面写具体的方法(其实具体的函数内容)
- 然后在main.m里面引用这个类来创建对象等等即可
我们先来看一下ASStudent.h里面的内容(就是怎么声明一个类的框架):
#import <Foundation/Foundation.h>
//声明的类是以@interface开始,@end结束,这些是刚刚新建后自动生成的
@interface ASStudent:NSObject{
//变量一定要写在花括号{}里面
@protected //默认都是protected,可省略
NSString *name; //之所以有个*,是因为这里定义的变量其实是个指针
@private
NSString *sid;
@public //只有public变量才能被直接调用
unsigned int age;
}
//方法也就是函数,通常写在这里,具体后面讲,这里先留个印象
-(void)setName:(NSString*)aName; //函数和public变量一样可被直接调用访问
-(NSString*) name;
@end
我们再来看一下ASStudent.m里的内容(就是怎么具体写函数的):
#import "ASStudent.h"
//这个开始和结束也是自动生成好了的
@implementation ASStudent
//下面是设置姓名的函数,setName是函数名,aName是变量参数,(NSString*)是指定这变量参数类型
-(void) setName:(NSString*)aName{
name=aName
}
//下面是返回调用姓名的函数
-(NSString*)name{
return name;
}
@end
我们再来看一下主函数中是怎么使用这个类的:
#import <Foundation/Foundation.h>
#import "ASStudent.h" //需要引入这个类才能使用
int main(int argc,const char * argv[]){
@autoreleasepool{
ASStudent * student=[[ASStudent alloc] init] //实例化出一个对象,就是创建,并初始化
student->age=20; //因为age是public所以可直接调用并赋值
[student setName:@"tom"]; //调用函数来给name赋值
NSLog("%@",[student name]); //调用name也不能直接调用,而是通过函数来调用
//而sid由于既不能直接调用,又没有函数来操作它,所以没法子用
}
return 0;
}
了解整个流程和顺序后,我们回头重点看一下方法也就是函数的解读:
(1)方法的类型有两种,一种是类方法(Class Method),前面是加号+;另一种是实例方法(Instance Method),前面是减号 - 。区别就是实例方法如上面我们的例子一样,需要先实例化即创建一个对象student出来,然后用这个student对象来调用这个方法。而类方法,则不需要实例化个对象,而直接用类来调用即可。如下:
在ASStudent.h里面增加一个方法:
//类方法前面是加号+,如果没有参数则直接写个函数名即可
+(void)print;
在ASStudent.m里面写这个方法具体的内容:
+(void)print{
NSLog(@"我是类方法!");
}
下面是最重点的,直接用类来调用:
//实例方法是用student对象来调用,而类方法是直接来调用
[ASStudent print];
(2)方法的签名:其实就是方法名称+参数,不包括括号里面的返回值和参数类型这些。方法的签名不能一样,也就是我们通常讲的“你不能定义两个一模一样的方法,那就乱套了”。怎么判断方法是否重名?去掉括号里面的返回值和参数类型,再看是否一样?是就重名。如:
//去掉括号里的返回值类型,一样的,所以重名
-(void)name;
-(NSString*)name;
//去掉返回值类型和参数类型,不一样,所以不重名
-(void)name:(int)a;
-(NSString*)name;
//重名
-(void)name:(int)a;
-(NSString*)name:(NSString*)a;
最后补充:
- 实例方法(Instance Method)里面可以直接引用实例变量;
- 方法都是公有public的,但如过这个方法只在实现(ASStudent.m)里出现,没有在声明(ASStudent.h)里出现,那么可以认为是私有的(初学者可以自动忽略这么复杂的话);
- 之前创建出的student要释放掉,加一个[student release]; alloc和release一般要配对使用。