一直以来都特别想讲讲对于属性和成员变量的区别,那么下面就让我们来讨论讨论这二者的区别吧,看看为什么苹果需要搞一个属性这么个玩意儿。
首先讲讲成员变量的写法,一般是下面:
@interfacePerson :NSObject
{
//定义成员变量
int_age;
}
定义属性则是:
@property(nonatomic,strong) NSString *name;
对于成员变量来说有两点值得注意和思考
1. 为什么成员变量的定义要加下划线
2. 为什么对于成员变量的访问需要getter和setter方法
其实对于上面的两个答案,很简单。首先你需要知道的是什么是成员变量以及成员变量的特点。
我们把Objective-C中写在类声明的大括号中的变量称之为成员变量(也称为属性,实例变量)。就是上述写的定义成员变量的格式。
成员变量的特点:
成员变量只能通过对象来访问
成员变量不能离开类,离开类之后就不是成员变量
成员变量不能再定义的同时进行初始化
成员变量存储在当前对象对应的堆的存储空间中,不会被自动释放,只能手动释放
成员变量前加下划线"_"是苹果的编程规范,或者说是程序员的习惯。这样写的好处在下边会提到
既然成员变量无法再外界进行访问那么我们如何去拿到想要访问的成员变量呢,请看下面的例子:
我先在Person.h文件中定义一个成员变量
@interfacePerson :NSObject
{
int_age;
}
然后在viewController中去访问
Person *person = [[Person alloc] init];
NSLog(@"%d",person.age);
结果会报错。报错的原因很自然,因为在OC中点语法是为getter和setter服务的,我定义一个成员变量但是没有实现该变量的getter和setter方法,所以我妄图通过点语法去访问该变量简直是不可能。
所以针对该情况,我们需要去实现该成员变量的getter和setter的方法。
代码如下:
Person.h
-(void)setAge:(int)age;
-(int)age;
Preson.m
-(void)setAge:(int)age{
_age = age;
}
-(int)age{
return _age;
}
现在我在viewController的viewDidLoad中去实现以下代码:
Person*person = [[Person alloc] init];
[person setAge:10];
NSLog(@"%d",[person age]);
打印的结果当然是正确的10
所以为了在外界也能够访问类中声明的成员变量所以我们需要定义和实现getter和setter方法,这就解释了上面的第二个问题。
通过上面的getter和setter的代码实现,不知道大家看出来什么没有,如果你不用_age,你试试看能否实现setter方法,很明显是不可以的,因为造成的结果是age=age,显然不对,所以为了区别成员变量和参数所以我们需要在成员变量前加下划线,当然你也可以自定义参数名就不用加下划线,但是显然我们需要用苹果推荐的编码方式。
那么了解了成员变量之后,我们可以说说属性@property了
其实@property在iOS5以后可以理解为苹果为了方便大众,将getter和setter方法在定义属性的时候一并给我们自动实现了,你无须去再手动去实现getter和setter方法,当然了,如果你需要在getter和setter方法中想要做点事情,你直接重写就好。
顺带地,@property还会生成一个成员变量,变量名就是_属性名,当然这个名字你也可以该,方法是在.m文件中的implements中去定义。
@synthesize name = myName;
如果你这样做了,那么变量名改为myName而不再是_name,当然了改名字我感觉很鸡肋,一边情况下没必要。
稍微总结一下,对于@property可以用一个等式去理解:
@property = 成员变量 + getter + setter