OC中的方法
方法:类的功能代码,在<.h>文件中声明,在<.m>文件中实现。
语法:
-|+(返回值类型)方法名:(参数类型)参数名
{
//方法体
}
示例:
-(void)sayHi;//无返回值类型的实例方法
-(void)sayHello:(NSString *)name;//无返回值类型有参数的实例方法
+(void)hiGuys;//无返回值类型的类方法
+(void)sayHey;
(-)表示:实例方法,实例方法只能通过创建对象来调用
(+)表示:类方法,类方法的使用注意以下四点:
- 类方法可以调用类方法
- 类方法不可以调用实例方法,但是类方法可以通过创建对象来访问实例方法
- 类方法不能使用实例变量,但是可以使用self,因为self不是实例变量
- 类方法作为消息可以被发送到类里面去,但是不能发送到对象中去
示例:
<.h>文件中
-(void)sayHello;//实例方法的声明
//没有返回值,但是有参数的实例方法
-(void)sayHelloName:(NSString *)name
Age:(NSInteger)age;
+(void)sayHi;
+(void)hiGuys;
<.m>文件中
-(void)sayHello{
NSLog(@"sayHello!");
}
-(void)sayHelloName:(NSString *)name
Age:(NSInteger)age{
NSLog(@"Hello guys!My name is %@,I am %ld years old.",name,age);
}
+(void)sayHi{
NSLog(@"sayHi");
}
+(void)hiGuys{
//1.类方法可以调用类方法
//self代表当前对象的指针???
[self sayHi];
//2.类方法不可以调用实例方法,但是类方法可以通过创建对象来访问实例方法
Person *person = [Person new];
[person sayHello];
//3.类方法不可以使用实例变量,以下代码不能通过编译
//NSLog(@"name:%@,age:%ld,hobby:%@",_name,_age,hobby);
在main函数中运行
Person *personA = [[Person alloc] init];
[personA sayHello];
[personA sayHelloName:@"大学生" Age:20];
//类方法作为消息,可以被发送到类里面去,不能发送到对象里面去。
[Person sayHi];
[Person hiGuys];
//[personA sayHi];不能通过编译
运行结果
2016-08-04 09:22:09.709 OC_02[713:21587] sayHello!
2016-08-04 09:22:09.710 OC_02[713:21587] Hello guys!My name is 大学生,I am 20 years old.
2016-08-04 09:22:09.711 OC_02[713:21587] sayHi
2016-08-04 09:22:09.711 OC_02[713:21587] sayHi
2016-08-04 09:22:09.711 OC_02[713:21587] sayHello!
设置器与访问器
变量有三个作用域,分别是:@public @protected @private,为了和其他对象交换信息,我们使用@public关键字,但是过多使用@public关键字,相当于暴露了内部细节,会带来极大的隐患。为了封装和安全我们希望使用private和protected类型,为了交换信息我们希望使用public类型,者两者似乎不可调和,这时存取方法(getter和setter)就应运而生了。
设置器(setter)与访问器(getter)的作用:
- 隐藏了实例变量
- 控制实例变量的读写
- 做正确性的校验
设置器与访问器的命名规则:
- 设置器:-(void)set首字母大写的实例变量:(实例变量的返回值类型)去掉下划线的实例变量名
- 访问器:-(实例变量的返回值类型)去掉下划线的实例变量名
示例:
<.h>文件中
{
NSString *_name;
NSInteger _age;
NSString *_hobby;
}
//设置器与访问器
//对于_name属性的设置器
-(void)setName:(NSString *)name;
//访问器
-(NSString *)name;
//_age属性的设置器
-(void)setAge:(NSInteger)age;
//访问器
-(NSInteger)age;
//hobby的设置器
-(void)setHobby:(NSString *)hobby;
//hobby的访问器
-(NSString *)hobby;
/*note:
对于类的名称,其首字母大写
对于变量,其首字母小写
遵循驼峰命名规则*/
<.m>文件中
-(void)setName:(NSString *)name{
_name = name;
}
-(NSString *)name{
return _name;
}
-(void)setAge:(NSInteger)age{
if (age < 18) {
_age = 18;
}
else{
_age = age;
}
}
-(NSInteger)age{
return _age;
}
//正确性校验
-(void)setHobby:(NSString *)hobby{
if ([hobby isEqualToString:@"play LOL"]) {
_hobby = @"niuB";
}
else{
_hobby = @"lowB";
}
}
-(NSString *)hobby{
return _hobby;
}
在main函数中运行
Student *studentA = [[Student alloc] init];
[studentA setName:@"Jack"];
[studentA setAge:20];
[studentA setHobby:@"play LOL"];
NSString *name = [studentA name];
NSInteger age = [studentA age];
NSString *hobby = [studentA hobby];
NSLog(@"name=%@,age=%ld,hobby=%@",name,age,hobby);
/*getter 和 setter的好处:
1.在setter中可以加入合法性检查,比如设置颜色的函数中,对于RGB颜色要判断其值在0~155之间
2.更新与被设置变量相关的其他变量的值,比如在一个潜水艇模拟系统中,改变了其水下深度时,要相应的更新所受压强
3.在debug时,可以在其中,尤其是在setter中加入追踪log
4.在多线程环境中,如果要保护对象的并发访问,则必须在getter/setter中加入同步锁
缺点:手动编写,比较麻烦*/
运行结果
2016-08-04 12:14:43.863 OC_02[1054:58526] name=Jack,age=20,hobby=niuB
便利初始化函数及便利构造器
为了解决在ini方法调用时传入个性化数据,可以使用自定义的便利初始化函数,框架类库中的一些类里有一系列的以init开头的方法,这些方法就是便利初始化函数。便利构造器只不过是把对象分配内存和调用便利初始化函数初始化对象的代码封装起来,让用户使用起来更方便。
示例:
<.h>文件中
{
NSString *_name;
NSInteger _age;
}
-(void)sayWord;
/*
便利初始化函数
注意命名规范:init开头
*/
-(id)initWithName:(NSString *)name
Age:(NSInteger)age;
/*
便利构造器
便利构造器只不过是把对象分配内存和调用便利初始化函数初始化对象的代码封装起来,让用户使用起来更方便
*/
+(id)teacherWithName:(NSString *)name
Age:(NSInteger)age;
<.m>文件中
@implementation Teacher
-(void)sayWord{
NSLog(@"我是Teacher,姓名:%@,年龄:%ld",_name,_age);
}
/*
id:返回类型是id数据类型,它是动态数据类型,可以指向任何类的对象,而不关心其具体类型,在运行时检查其具体类型,可以对其发送任何(存在的)消息
self:指当前对象的指针
super:指向父类对象的指针,子类使用super发送消息时,实际上就是告诉子类调用父类的方法。如果父类没有定义该方法,则继续在继承链上查找,直到寻找到位置,如果找到NSObject的位置还没找到,就会报错
*/
-(id)init{
if (self = [super init]) {
_name = @"ZCQ";
_age = 24;
}
return self;
}
-(id)initWithName:(NSString *)name
Age:(NSInteger)age{
if (self = [super init]) {
_name = name;
_age = age;
}
return self;
}
+(id)teacherWithName:(NSString *)name Age:(NSInteger)age{
Teacher *teacher = [[Teacher alloc] initWithName:name Age:age];
return teacher;
}
在main函数中运行
//便利初始化函数 以及 便利构造器
Teacher *teacher = [[Teacher alloc] init];
[teacher sayWord];
Teacher *teacher1 = [[Teacher alloc] initWithName:@"大师" Age:100];
[teacher1 sayWord];
Teacher *teacher2 = [Teacher teacherWithName:@"齐天大圣" Age:200];
[teacher2 sayWord];
运行结果
2016-08-04 12:14:43.863 OC_02[1054:58526] 我是Teacher,姓名:ZCQ,年龄:24
2016-08-04 12:14:43.864 OC_02[1054:58526] 我是Teacher,姓名:大师,年龄:100
2016-08-04 12:14:43.864 OC_02[1054:58526] 我是Teacher,姓名:齐天大圣,年龄:200