0x00 前言
Objective-C中,类的成员变量按可访问权限可分为三种@public
、@private
、@protected
,想要使用类对象访问到成员变量就必须把成员变量权限修饰为@public
,这样做类对象就可以随意读取或修改成员变量的值了。但是,这样的做法会导致数据有效性和可靠性变低,想要让某个成员变量的值变成只读也是不可能的。这就有了getter和setter方法的出现。
注意:在声明类的时候,不要把成员变量修饰成
@public
权限,最好先通过getter方法和setter方法来封装。
0x01 getter、setter方法声明与实现
声明与实现例子:
@interface Person:NSObject //声明Person类
{
NSString *_name;
NSString *_sex;
int age;
}
//————getter方法声明————
-(NSString *)name;
-(NSString *)sex;
-(int)age;
//————setter方法声明————
-(void)setName:(NSString *)name;
-(void)setSex:(NSString *)sex;
-(void)setAge:(int) age;
@end
@implementation Person //实现Person类
//————getter方法实现————
-(NSString *)name{
return _name;
}
-(NSString *)sex{
return _sex;
}
-(int)age{
return _age;
}
//————setter方法实现————
-(void)setName:(NSString *)name{
_name = name;
}
-(void)setSex:(NSString *)sex{
if (![sex isEqual: @"男"] || ![sex isEqual: @"女"]) {
NSLog(@"干啥玩意呢,能不能好好的设置性别!");
}
else{
_sex = sex;
}
}
-(void)setAge:(int) age{
_age = age;
}
@end
getter、setter方法命名都有一些约定,自己实现的时候最好参见约定来写。
getter方法
- 方法名为成员变量名去掉下划线;
- getter方法没有参数;
- getter方法返回值与成员变量保持一致。
setter方法
以set打头,后面跟成员变量名去掉下划线(首字母大写);
形参名也最好是成员变量名去掉下划线;
setter方法返回值为空。
0x02 getter、setter方法调用方式
调用getter、setter方法有两种方式,如下:
Person *xm = [[Person alloc] init];
//————方式1:一般方法调用方式————
[xm setName: @"小明"];
[xm setSex: @"男"];
[xm setAge: 10];
NSLog(@"name = %@, sex = %@, age = %d",[xm name],[xm sex],[xm age]);
//————方式2:点语法方式————
xm.name = @"小明";
xm.sex = @"男";
xm.age = 10;
NSLog(@"name = %@, sex = %@, age = %d",xm.name,xm.sex,xm.age);
从上面例子也可以看出方式2的语法要简洁、好看得多,所以也推荐使用点语法的方式。点语法格式为:对象名.方法名
,在调用非getter、setter方法时还是用老方法,不要用点语法方式。
点语法属于编译器语法,在Xcode编译的时候,它会自动帮我们替换成方式1的写法。
0x03 @property、@synthesize关键字的使用
上面的内容学会了getter、setter方法的声明、实现、调用。相比用惯了C#的我来说,还是觉得每次都这样写getter、setter方法是一件很繁琐的事情(被VS里面的Ctrl + R,E惯坏了)。还好Xcode里面有@property(声明属性的访问器)
、@synthesize(实现属性的访问器)
两个关键字带我飞,它们都是编译器指令,用来自动生成getter、setter方法,示例如下:
@interface Person:NSObject //声明Person类
{
NSString *_name;
NSString *_sex;
int _age;
}
@property NSString *name,*sex;
@property int age;
@end
@implementation Person //实现Person类
@synthesize name = _name; //如果不给name赋值,它将自动生成一个name的成员变量,关联不到_name
@synthesize sex = _sex;
@synthesize age = _age;
@end
在Xcode 4.4及之前的版本,@property
只帮我们声明getter、setter方法,两个关键字需要配套使用(以上示例是Xcode4.4及之前的版本)。在之后的版本,它帮我们声明、实现getter、setter方法,如果没有声明下划线打头的变量,它自动帮我们生成,@synthesize
是可以忽略的,示例如下:
@interface Person:NSObject //声明Person类
@property NSString *name,*sex;
@property int age;
@end
@implementation Person //实现Person类
@end
注意:
- 手动实现了getter方法,编译的时候就只生成setter方法和成员变量;
- 手动实现了setter方法,编译的时候就只生成getter方法和成员变量;
- getter、setter方法都手动实现了,它将不会生成成员变量,并且会报错。
0x04 总结
@property
关键字会同时生成getter、setter方法,如果一个属性只需要只读,不能用关键字自动生成(个人理解,不知道是不是没看到有这个知识点)。关键字生成的成员变量、方法名命名方式均为0x01里所说约定,所以自己手动实现的时候为了保持一致性,最好遵从约定。