转载请标明出处:blog.csdn.net/zhangxingping
属性的声明
属性的声明使用关键字@property。属性的声明可以是在@interface类中的方法声明块的任何地方。@property同样也可以在protocal(协议)和category(种类)中。其通用形式如下:
@property ( attributes) type name
由于英文property 和attribute在汉语中都有属性的含义,为了避免混淆,暂且不对这两个词汇进行翻译。其中的attributes是用来描述名称为name的property的属性的;type表明了名称为name的property的类型,这里的类型可以是任何的objective-c的类和POD类型(关于POD参见:http://www.fnal.gov/docs/working-groups/fpcltf/Pkg/ISOcxx/doc/POD.html )类型;name表示属性的名称。
其中,attribute可以是用逗号间隔的一组描述信息 ,这一组描述信息共同修饰后面的名称为name的property。这些描述信息可以分成如下几种:
1. 访问方法名称相关
缺省的Setter()方法名称为:set+属性名称 ;
缺省的Getter()方法名称为:属性名称;
访问方法的名称可以通过以下的方式来进行显示地指定:
指定Setter()方法的名称:setter =方法名称;其中该方法应该是只有一个参数,且参数的类型与property的类型一致;方法的返回类型必须是void类型。
指定Getter()方法的名称:getter = 方法名称;其中该方法的返回值应该和该 property的类型一致,并且不需要返回值。
2. property的可读写性
缺省情况下,property是可读写的:readwrite,也就是说Getter和Setter方法都是存在的。还可以指定property为readonly,即该 property是只读的。此时property就不应该有setter方法。(没有看到过 writeonly的property,可能是因为这样的property没有什么实际的用处吧。)
3. 关于setter的一些细节
下面的关键字用于描述setter方法应该如何设置property的值:
assign
表明setter方法只是进行简单的赋值运算。这个是缺省的。通常对于标量类型以及不属于该类的对象使用assign来进行描述。比如delegate。(标量,scalar type 是与aggregate type 相对而言的。scalar type代表的是一个简单的数值,如语言内置的数据类型基本上都是scalar type的;aggregate type代表的是相同类型的或者是不同类型的多个值,如数组,结构体,类等。)
retain
表明setter方法应该对新的值发送retain消息,或者说调用新值的retain方法。旧值会被发送release消息。
copy
表明setter方法中在进行赋值时应该进行拷贝赋值。旧值会被发送release消息。通过调用新值的copy方法来赋值给该property。这种赋值方式只适用于对象类型,并且要求该对象遵循NSCopying协议。
上述的这些关键字是相互排斥的,也就是说同时只能使用一种。
4. 关于多线程(原子性)
可以使用nonatomic关键字来表明该property是非原子的。缺省情况下property都是原子的,这样可以在多线程环境下提供对数据的安全访问 。
另外,还有IBOutlet关键字用来表示该property是Interface Builder的一个outlet。它不是正式的property attribute。
来看看在之前的程序中属性name的类型为NSString*,这不是一个基本的数据类型,而name属性本身是属于Student类的对象的,因此在缺省的情况下name的setter方法将采用assign的方式进行赋值,这是不太合理的。采用retain的方式来进行赋值比较合理一些。修改上面的程序如下:
Student.h:
- #import <Foundation/Foundation.h>
- @interface Student : NSObject
- {
- @private
- NSString * name; //学生的姓名
- float math; //数学科目的成绩
- float english; //英语科目的成绩
- }
- //增加retain关键字,按照内存管理的基本原则,在dealloc的时候需要发送release消息给name
- @property (retain) NSString * name;
- @property float math;
- @property float english;
- -(id)initWithName:(NSString*)aName math:(float)scoreMath english:(float)scoreEnglish;
- //-(NSString *)getName;
- //-(float)getMath;
- //-(float)getEnglish;
- @end
Student.m如下:
- #import "Student.h"
- @implementation Student
- @synthesize name;
- @synthesize math;
- @synthesize english;
- - (id)init
- {
- self = [super init];
- if (self)
- {
- name = nil;
- math = 0;
- english = 0;
- }
- return self;
- }
- -(id)initWithName:(NSString*)aName math:(float)scoreMath english:(float)scoreEnglish
- {
- self = [super init];
- if (self)
- {
- name = aName;
- math = scoreMath;
- english = scoreEnglish;
- }
- return self;
- }
- //-(NSString *)getName
- //{
- // return name;
- //}
- //
- //-(float)getMath
- //{
- // return math;
- //}
- //
- //-(float)getEnglish
- //{
- // return english;
- //}
- //
- //- (void)dealloc
- //{
- // [super dealloc];
- //}
- -(void) dealloc
- {
- [name release]; //销毁对象的时候发送release消息给name。
- [super dealloc];
- }
- @end
main.m保持不变。此时编译,发现之前出现的编译警告消失了。程序输出结果如下:
Name:Tony
Math:99.000000
Math:89.980003
结果正确。