Objective-C - OC访问器学习笔记
设置和获取类成员变量的值是采用面向对象语言编程时非常常见的操作,通常程序员编程时需要提供setter
和getter
方法用于成员变量的访问。自定义访问器会使源码的长度增加,变得臃肿不堪,因此OC中提供一种简明语法@property
来简化这一过程。
自定义访问器
虽然OC中提供了简明的访问器定义语法但是仍然可以自定义成员访问器,定义方式和其他的编程语言没什么太大的差别。下面定义了一个类NSPerson1
,NSPerson1
继承自NSObject
,并且有两个成员变量_heightInMeters
和_weightInKilos
。
@interface BNRPerson1 : NSObject
{
// 成员变量写在括号里面,并且以_作为前缀
float _heightInMeters;
int _weightInKilos;
}
// 方法写在外面
// getter方法命名与变量同名
- (float)heightInMeters;
// setter方法命名在之前加set
- (void)setHeightInMeters:(float)h;
- (int)weightInKilos;
- (void)setWeightInKilos:(int)w;
// 身体质量指数
- (float)bodyMassIndex;
@end
NSPerson1
类实现部分,代码好长,但是熵比较低:
@implementation BNRPerson1
- (float)heightInMeters
{
return _heightInMeters;
}
- (void)setHeightInMeters:(float)h
{
_heightInMeters = h;
}
- (int)weightInKilos
{
return _weightInKilos;
}
- (void)setWeightInKilos:(int)w
{
_weightInKilos = w;
}
- (float)bodyMassIndex
{
return _weightInKilos / (_heightInMeters * _heightInMeters);
}
@end
OC中访问器命名惯例
命名惯例并非语言必须,而是大家约定俗成的编码方式,不要在这里乱搞“创新”。
- 成员变量命名前以
_
作为前缀。 getter
方法与成员变量名称相同,但是把前缀_
去除。setter
方法参考实例代码中的命名方式,文字不好表述。
使用@property定义访问器
自定义访问器代码繁杂而无趣,使人心情焦躁,降低编程效率,徒增代码量,因此OC中提供了@property
的方式来定义访问器。将繁杂而重复的工作交给编译器做,程序员只需要在代码中声明需要定义访问器的成员变量便可。
NSPerson2
是采用@proerty
简明语法创建的类,功能与NSPerson2
完全相同,但是代码显然要简练的多,看上去也舒服。
NSPerson2
类定义:
@interface BNRPerson2 : NSObject
// 使用property使得编译器自动生成访问器
// 指明访问器属性和成员变量类型
@property (nonatomic) float heightInMeters;
@property (nonatomic) int weightInKilos;
// 身体质量指数
- (float)bodyMassIndex;
@end
NSPerson2
类实现:
@implementation BNRPerson2
- (float)bodyMassIndex
{
// 使用self指针调用成员方法
return [self weightInKilos] / ([self heightInMeters] * [self heightInMeters]);
// 仍然可以以属性名访问
// return _weightInKilos / (_heightInMeters * _heightInMeters);
}
@end
注意:
同时在方法的实现中,访问类成员变量时仍然可以以变量名(以_
开头的变量名)访问。但是不推荐。
访问器定义方法
以NSPerson2
中的成员变量heightInMeters
为例说明定义方法。
@property (nonatomic) float heightInMeters;
@property
访问器定义关键字。(nonatomic)
为访问器属性,多个属性之间要用逗号隔开,后面会细说。float
为成员变量的类型,此处为浮点数。heightInMeters
为成员变量。;
又怎能忘了分号:-)。
访问器属性
访问器定义中的第二项为访问器属性,访问器属性指明了成员变量的访问方式。仍然以例子来说明,下面为类成员变量heightInMeters
定义了访问器,其属性为nonatomic
和readwrite
,表明heightInMeters
是非原子的,而且可读写。
@property (nonatomic,readwrite) float heightInMeters;
也可以指定访问器属性为readonly
,这样编译器只会为heightInMeters
生成getter
方法heightInMeters
,而不会生成setter
方法setHeightInMeters
,以此来控制类成员变量的访问方式。
访问属性有默认与非默认之分,非默认属性需要显式指明。例如readwrite
为默认的访问器属性,因此不需要显式指出,而nonautomic
为非默认访问器属性,默认的为automic
,定义时需要显式指出。
点记法访问成员变量
成员变量的访问可以采用点记法(OC提供的一种成员变量访问的简明语法),采用点记法使得代码可读性进一步提高。比如下面例子中访问成员变量weightInKilos
和heightInMeters
。
- (float)bodyMassIndex
{
// 使用点记法访问成员(推荐)
return self.weightInKilos / (self.heightInMeters * self.heightInMeters);
}
点记法说明
点记法访问成员变量和调用访问器访问完全一样,也即:
子中访问成员变量weightInKilos
和heightInMeters
。例如下面两种访问方式等价。
int w = self.weightInKilos;
int w = [self weightInKilos];
点记法可以获取成员变量的值,也可以设置成员变量的值。作为左值出现为获取,作为右值出现为设置。
int w = self.weightInKilos;
int w = 7;
self.weightInKilos = w;
注意:
像NSPerson1
中虽然没有通过@property
定义访问器,但是仍然可以采用点记法访问成员变量。
成员方法也可以通过点记法的方式调用。