[Objective-C] property setter/getter @property属性

注:这里暂不涉及 @property 定义时的 assign/retain/copy、atomic/nonatomic、readonly/readwrite 属性

环境
Mac OS Yosemite (10.10) + XCode 6.1.1

Pracitce #1

[objc]  view plain  copy
  1. // ========= Person.h =========  
  2. @interface Person: NSObject  
  3. {  
  4. }  
  5. -(void) Print;  
  6. @property NSString* name;  
  7. @end  
  8.   
  9. // ========= Person.m =========  
  10. #import "Person.h"  
  11. @implementation Person  
  12. -(void) Print {  
  13.     NSLog(@"Print_Name:%@", _name);    // #100  
  14. }  
  15. @end  
  16.   
  17. // ========= main.mm =========  
  18. #import <Foundation/Foundation.h>  
  19. #import "Person.h"  
  20.   
  21. int main(int argc, const charchar * argv[]) {  
  22.     @autoreleasepool {  
  23.           Person* p = [[Person alloc] init];  
  24.           [p setName:@"Henry"];  
  25.           NSLog(@"Name:%@", [p name]);  
  26.           [p Print];  
  27.     }  
  28. }  

> Name:Henry
> Print_Name:Henry

说明:
1)@property以及@synthesize等其他directive发挥作用是在预处理阶段,即先按照这些directive的语义将其名下的代码预处理成真正的Objc的代码, 比如这里的@property NSString* name会被预处理成真正的类属性“_name”,并为其生成setter/getter方法(name 和 setName)的代码。在这之后,才会真正开始编译。(所有的新一代语言都差不多,不必理会)
2)在 #100 处,虽然代码中没有显式定义 _name 的属性,如果是 C++ 代码会报错的,然而这里的 @property name 会在预处理阶段自动生成 _name 属性,因此这里不会报错。

Pracitce #2

[objc]  view plain  copy
  1. // ========= Person.h =========  
  2. @interface Person: NSObject  
  3. {  
  4. @public  
  5.     NSString* name;     // #200  
  6. }  
  7. -(void) Print;  
  8. @property NSString* name;  
  9. @end  
  10.   
  11. // ========= Person.m =========  
  12. #import "Person.h"  
  13. @implementation Person     // #201  
  14. -(void) Print {  
  15.     NSLog(@"PrintName:%@", name);     // #202  
  16.      NSLog(@"Print_Name:%@", _name);  
  17. }  
  18. @end  
  19.   
  20. // ========= main.mm =========  
  21. #import <Foundation/Foundation.h>  
  22. #import "Person.h"  
  23.   
  24. int main(int argc, const charchar * argv[]) {  
  25.     @autoreleasepool {  
  26.           Person* p = [[Person alloc] init];  
  27.           [p setName:@"Henry"];  
  28.           NSLog(@"Name:%@", [p name]);  
  29.           [p Print];  
  30.     }  
  31. }  

> Name:Henry
> PrintName:(null)
> Print_Name:Henry

说明:
1) #201 处会出现warning: Autosynthesized property 'name' will use synthesized instance variable '_name', not existing instance variable 'name'
2) #200 处新加了一个名为 name 的属性,这时会存在两个 name 属性,一个是由 @property NSString* name 自动生成的 _name 属性,另一个是手工添加的 name 属性,前者默认是 private 的,后者被手工指定为 public 的。
3) setter/getter 方法只为 _name 属性提供服务,如果不手工定义 setter/getter 方法的实现,它们会忽略 name 属性,即 #201 处的 warning 所指。
4) 既没有通过 @property 指令定义,又没有手工定义 setter/getter 方法的属性,是不能被类的外部访问到的,即使它是 public 的。

Pracitce #3

[objc]  view plain  copy
  1. // ========= Person.h =========  
  2. @interface Person: NSObject  
  3. {  
  4. @public  
  5.     NSString* name;  
  6. }  
  7. -(void) Print;  
  8. @property NSString* name;  
  9. @end  
  10.   
  11. // ========= Person.m =========  
  12. #import "Person.h"  
  13. @implementation Person  
  14. @syntheize name = _name;     // #300  
  15. -(void) Print {  
  16.     NSLog(@"PrintName:%@", name);  
  17.      NSLog(@"Print_Name:%@", _name);  
  18. }  
  19. @end  
  20.   
  21. // ========= main.mm =========  
  22. #import <Foundation/Foundation.h>  
  23. #import "Person.h"  
  24.   
  25. int main(int argc, const charchar * argv[]) {  
  26.     @autoreleasepool {  
  27.           Person* p = [[Person alloc] init];  
  28.           [p setName:@"Henry"];  
  29.           NSLog(@"Name:%@", [p name]);  
  30.           [p Print];  
  31.     }  
  32. }  

> Name:Henry
> PrintName:(null)
> Print_Name:Henry

说明:
1) #300 处新加了一个名为 name 的属性,这时会存在两个 name 属性,一个是由 @property NSString* name 自动生成的 _name 属性,另一个是手工添加的 name 属性,前者默认是 private 的,后者被手工指定为 public 的。
2) setter/getter 方法只为 _name 属性提供服务,如果不手工定义 setter/getter 方法的实现,它们不会涉及到 name 属性。
3) @synthesize name 和 @synthesize name = _name 等价。
4) 从 Objective-C 2.0 开始,.m 文件中的 @synthesize name 或 @synthesize name = _name 可写可不写。

Pracitce #4

[objc]  view plain  copy
  1. // ========= Person.h =========  
  2. @interface Person: NSObject  
  3. {  
  4. @public  
  5.     NSString* name;     // #400  
  6. }  
  7. -(void) Print;  
  8. @property NSString* name;  
  9. @end  
  10.   
  11. // ========= Person.m =========  
  12. #import "Person.h"  
  13. @implementation Person  
  14. @syntheize name = name;     // #401  
  15. -(void) Print {  
  16.     NSLog(@"PrintName:%@", name);  
  17.      NSLog(@"Print_Name:%@", _name);     // #402  
  18. }  
  19. @end  
  20.   
  21. // ========= main.mm =========  
  22. #import <Foundation/Foundation.h>  
  23. #import "Person.h"  
  24.   
  25. int main(int argc, const charchar * argv[]) {  
  26.     @autoreleasepool {  
  27.           Person* p = [[Person alloc] init];  
  28.           [p setName:@"Henry"];  
  29.           NSLog(@"Name:%@", [p name]);  
  30.           [p Print];  
  31.     }  
  32. }  

> Name:Henry
> PrintName:(null)
> Print_Name:Henry

说明:
1) #401 处指定了“自动合成的”_name属性实际上将采用 Person.h 中 #400 处手工定义的 NSString* name 属性。
2) #402 处在编译时会报错:Use of undeclared identifier '_name'; did you mean 'name'?
3) 屏蔽 #402 处之后的运行结果:
> Name:Henry
>PrintName:Henry

综述

1) 在  Mac OS Yosemite (10.10) + XCode 6.1.1 的环境下,如果不需要为某个属性自定义 setter/getter 方法的话,在定义这个属性的时候,只需要在 .h 文件中类似 @property NSString* name 这样定义这个属性就可以了,getter/setter 方法会自动生成。
2) 不需要在 @interface 中手工定义该属性变量,也不需要在 .m 文件中再定义 @synthesize name 或 @synthesize name = _name。
3) 注意:这样自动生成的属性的变量名是以下划线开头的,类似 _name。

猜你喜欢

转载自blog.csdn.net/wlanye/article/details/79309096
今日推荐