按照先来后到的顺序,在了解@property之前,必须先了解
accessor(存取器)
的概念,这对于理解@property有很大帮助。
1.什么是存取器
accessor(存取器)
:顾名思义,指用于获取和设置对象实例变量的方法。《Cocoa Design Patterns》把它归类为基础模式中的一种。用于获取实例变量值的存取器是getter
,用于设置实例变量值的存取器是setter
。
在Cocoa中accessor(存取器)
有很多优点:
- 灵活性与方便维护:可在
accessor(存取器)
中改变并实现不同的实例变量访问方式而不影响其他代码,方便对实例变量的更改维护。 - 内存管理:
accessor(存取器)
方法提供了简单的方法把内存管理代码隔离在少部分代码中。 - 支持KVC和KVO:KVC和KVO是很强大的技术。但是它们依赖于正确命名
accessor(存取器)
。
2.那么怎么创建存取器呢
先上代码:
// h文件
import <Foundation/Foundation.h>
@interface Person : NSObject
{
// 实例变量
NSString *name;
}
// setter
- (void)setName:(NSString *)newName;
// getter
- (NSString *)name;
@end
上面的代码中name
就是Person
的实例变量,并且可以看到对这个实例变量声明了get/set
方法,即存取器
。
//m文件
#import "Person.h"
@implementation Person
// setter
- (void)name:(NSString *)newName
{
name = newName;
}
// getter
- (NSString *)name
{
return name;
}
// setter
@end
上面代码是对实例变量存取器的实现。我们可以看到,存取器就是对实例变量进行赋值和取值。按照约定赋值方法以set开头,取值方法以实例变量名命名。
如果要为实例变量赋值或取值,可以这样操作:
Person *person = [[Person alloc] init];
//赋值
[person setName:@"jack"];
//取值
[person name];
3.那么终于该说说@property和@synthesize了
accessor(存取器)
是很重要的技术,在用不同的方式来获取或设置实例变量时,accessor(存取器)
给了我们很大的灵活性,有时还涉及到内存管理。
但是有没有更方便的方式去完成accessor(存取器)
的工作呢,有——Objective-C 2.0
加入了@property
和@synthesize
,前者用于声明,后者用于合成accessor(存取器)
,结合使用就可以自动生成accessor(存取器)
了,也就是说,这两个关键字可以省略刚刚出现的大段略显累赘的代码。
不妨把刚才的代码翻译一下:
// h文件
#import <Foundation/Foundation.h>
@interface Person : NSObject
{
// 实例变量
NSString * name;
}
@property(nonatomic,strong) NSString * name;
@end
上面代码中使用@property声明了name
属性,名称与实例变量名称相同。
// m文件
#import "Person.h"
@implementation Person
@synthesize name;
@end
如上,m文件中使用@synthesize自动生成这name
实例变量的accessor(存取器)
,并且隐藏了它,使代码简洁了很多。
既然使用了新的关键字,存取值时也会有些不同:
Person *person = [[Person alloc] init];
//存取值
person.name = @"jack";
对比之前的代码,Person
对象使用点语法给存取器发送消息,区别于之前的方括号语法。并且get
与set
的语法是相同的,所以这里的点语法可以根据语境自动判断我们是要赋值还是取值。当然,毕竟是对之前accessor(存取器)
的简化,所以在这里方括号的语法也是可行的,操作时就跟之前的一样了。
所以
@ property
与@ synthesize
的作用就很清晰了,@ property
相当于声明实例变量的get/set
方法,@synthesize
相当于在m文件中实现实例变量的get/set
方法。而代码要比accessor(存取器)
简洁很多,存取时都可以使用点语法。
网友评论