Objective-C 实例变量与属性的区别

  记得刚学习OC时,对实例变量和属性总是不太清楚。

  比如下面代码中在打印Person类对象的名字时,什么时候用带“_”的name,NSLog(@"%@",p1->_name);

                        什么时候用不带“_”的name,NSLog(@"%@",p1.name);

  现在回想起来也是挺有意思的过往,写下自己曾经的迷惘,纪念一下青春?。。。。

 

首先,使用实例变量编写代码。以及实例变量赋值要用到getter、setter方法。

@interface Person : NSObject
{
  @public
  NSString *_name;                    //定义实例变量_name
}
-(instancetype)initWithName:(NSString *)name;  //初始化
-(void)setName:(NSString *)name;           //setter方法
-(NSString *)name;                   //getter方法
@end
@implementation Person               //实现部分
-(instancetype)initWithName:(NSString *)name{
    if (self = [super init]) {
        _name = name;
    }
    return self;
}
-(void)setName:(NSString *)name{
    _name = name;
}
-(NSString *)name{
    return _name;
}
@end
int main(int argc, const char * argv[]) {    //主函数
    Person *p1 = [[Person alloc] initWithName:@"zhangsan"];
    NSLog(@"%@",p1->_name);
    return 0;
}

  以上代码,均使用的是实例变量。这个大家应该都明白。那么什么时候不用下划线呢?

 

使用属性编写代码(请比较两者的代码量)

首先明确两点:

1、属性的作用是生成setter以及getter方法的实现。并且如果.h文件中未定义对应的实例变量时,系统会生成一个“_属性名”的实例变量,但是生成的实例变量的可见度是私有的private。

2、OC中提供属性的目的:为了简化程序员的编码。

@interface Person : NSObject
@property(nonatomic,copy)NSString *name;    
-(instancetype)initWithName:(NSString *)name;
@end

@implementation Person
-(instancetype)initWithName:(NSString *)name{
    if (self = [super init]) {
        _name = name;
    }
    return self;
}
@end

int main(int argc, const char * argv[]) {
    Person *p1 = [[Person alloc] initWithName:@"zhangsan"];
    NSLog(@"%@",p1.name);     //属性是一对getter、getter方法,点语法是属性的另一种调用格式。 
return 0;
}

  此时打印,虽然属性也生成了对应的实例变量,但是实例变量是私有的,所有并不能直接打印实例变量。用点语法,相当于调用了getter方法,返回值依旧是实例变量存储的值。

因为定义属性时语义设置的关键字是copy

setter内部实现

 - (void)setGender:(NSString *)gender {
   if (_gender != gender) {
       [_gender release];
       _gender = [gender copy];
   }

}

getter内部实现

 - (NSString *)gender {
   return  [[_gender retain] autorelease];

}

  说到这里,应该能够理解属性与实例变量的区别了。

 

posted @ 2016-02-29 20:01  哎呦,哈士奇  阅读(1722)  评论(0编辑  收藏  举报