关于属性
在C++中,通常需要编写Getter和Setter方法来获取或者是设置实例变量的值。这两种方法需要在程序中显示的完成。这种方式在Objective-C中也是适用的。但是Objective-C提供了一种更为便捷的方式来完成这种功能。它就是属性。和C++中的显示的Getter和Setter方法相比,属性机制使得Getter函数和Setter来的更容易和更简化。
Objectivc-C中的属性是通过关键字@property来声明的。
例如,有类如下:
Student.h文件:
- #import<Foundation/Foundation.h>
- @interfaceStudent:NSObject
- {
- @private
- NSString*name;//学生的姓名
- floatmath;//数学科目的成绩
- floatenglish;//英语科目的成绩
- }
- -(id)initWithName:(NSString*)aNamemath:(float)scoreMathenglish:(float)scoreEnglish;
- -(NSString*)getName;
- -(float)getMath;
- -(float)getEnglish;
- @end
Student.m文件:
- #import"Student.h"
- @implementationStudent
- -(id)init
- {
- self=[superinit];
- if(self)
- {
- name=nil;
- math=0;
- english=0;
- }
- returnself;
- }
- -(id)initWithName:(NSString*)aNamemath:(float)scoreMathenglish:(float)scoreEnglish
- {
- self=[superinit];
- if(self)
- {
- name=aName;
- math=scoreMath;
- english=scoreEnglish;
- }
- returnself;
- }
- -(NSString*)getName
- {
- returnname;
- }
- -(float)getMath
- {
- returnmath;
- }
- -(float)getEnglish
- {
- returnenglish;
- }
- -(void)dealloc
- {
- [superdealloc];
- }
- @end
main.m文件如下:
#import <Foundation/Foundation.h>
- #import"Student.h"
- intmain(intargc,constchar*argv[])
- {
- NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init];
- Student*p=[[Studentalloc]initWithName:@"Mark"math:80.0fenglish:100.00f];
- NSLog(@"Name:%@",[pgetName]);
- NSLog(@"Math:%f",[pgetMath]);
- NSLog(@"Math:%f",[pgetEnglish]);
- [prelease];
- [pooldrain];
- return0;
- }
上面程序的输出结果如下:
Name:Mark
Math:80.000000
Math:100.000000
上面的程序是通过C++中的方式来编写Getter方法来获取私有的实例变量的值。这些个Getter方法实现虽然简单,但是必需有程序员显示书写来完成。应用属性机制后,程序如下:
Student.h文件:
- #import<Foundation/Foundation.h>
- @interfaceStudent:NSObject
- {
- @private
- NSString*name;//学生的姓名
- floatmath;//数学科目的成绩
- floatenglish;//英语科目的成绩
- }
- @propertyNSString*name;
- @propertyfloatmath;
- @propertyfloatenglish;
- -(id)initWithName:(NSString*)aNamemath:(float)scoreMathenglish:(float)scoreEnglish;
- //-(NSString*)getName;
- //-(float)getMath;
- //-(float)getEnglish;
- @end
Student.m文件:
- #import"Student.h"
- @implementationStudent
- @synthesizename;
- @synthesizemath;
- @synthesizeenglish;
- -(id)init
- {
- self=[superinit];
- if(self)
- {
- name=nil;
- math=0;
- english=0;
- }
- returnself;
- }
- -(id)initWithName:(NSString*)aNamemath:(float)scoreMathenglish:(float)scoreEnglish
- {
- self=[superinit];
- if(self)
- {
- name=aName;
- math=scoreMath;
- english=scoreEnglish;
- }
- returnself;
- }
- //-(NSString*)getName
- //{
- //returnname;
- //}
- //
- //-(float)getMath
- //{
- //returnmath;
- //}
- //
- //-(float)getEnglish
- //{
- //returnenglish;
- //}
- //
- //-(void)dealloc
- //{
- //[superdealloc];
- //}
- @end
main.m文件如下:
- #import<Foundation/Foundation.h>
- #import"Student.h"
- intmain(intargc,constchar*argv[])
- {
- NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init];
- Student*p=[[Studentalloc]initWithName:@"Mark"math:80.0fenglish:100.00f];
- //NSLog(@"Name:%@",[pgetName]);
- //NSLog(@"Math:%f",[pgetMath]);
- //NSLog(@"Math:%f",[pgetEnglish]);
- NSLog(@"Name:%@",p.name);
- NSLog(@"Math:%f",p.math);
- NSLog(@"Math:%f",p.english);
- [prelease];
- [pooldrain];
- return0;
- }
程序的输出如下:
Name:Mark
Math:80.000000
Math:100.000000
可见属性机制使得程序更加简洁明了。
上面程序中引入了新的关键字@synthesize,这个关键字告诉编译器自动为其后面的属性生成Getter()和Setter()方法。需要注意的一点是虽然在描述上适用的是“自动生成Getter()和Setter()方法”,但是实际上我们并看不到生成的对应代码。需要明确的是编译器自动生成的Getter方法:name(),math(),english()以及Sette方法:setName(), setMath(), setEnglish()的调用完全和普通的方法是一样的。例如我们可以修改上面的main()函数如下:
- #import<Foundation/Foundation.h>
- #import"Student.h"
- intmain(intargc,constchar*argv[])
- {
- NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init];
- Student*p=[[Studentalloc]initWithName:@"Mark"math:80.0fenglish:100.00f];
- //NSLog(@"Name:%@",[pgetName]);
- //NSLog(@"Math:%f",[pgetMath]);
- //NSLog(@"Math:%f",[pgetEnglish]);
- //NSLog(@"Name:%@",p.name);
- //NSLog(@"Math:%f",p.math);
- //NSLog(@"Math:%f",p.english);
- [psetName:@"Tony"];
- [psetMath:99.0f];
- [psetEnglish:89.98f];
- NSLog(@"Name:%@",[pname]);
- NSLog(@"Math:%f",[pmath]);
- NSLog(@"Math:%f",[penglish]);
- [prelease];
- [pooldrain];
- return0;
- }
程序输出为:
Name:Tony
Math:99.000000
Math:89.980003
上面的程序在Xcode中编译后,会在@property NSString * name;代码的所在行头看到一个黄色的叹号,这表明编译器在该行代码处给出了编译警告。单击该黄色叹号可以看到给出的警告信息:“No 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed”和“Default property attribute 'assign' not appropriate for non-gc object”。警告信息的意思是:“没有明确指出应该是assign还是retain或者是copy,却省的是assign”和“缺省得属性设置assign不适合非gc对象 ”,那么这两个警告信息的含义具体是什么呢?assign,retian,copy又分别代表什么含义呢?什么是gc对象呢?什么是非gc对象呢?这些问题见后文描述。