您的位置:首页 > 移动开发 > Objective-C

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

2018-02-11 10:52 495 查看

注:这里暂不涉及 @property 定义时的 assign/retain/copy、atomic/nonatomic、readonly/readwrite 属性
环境Mac OS Yosemite (10.10) + XCode 6.1.1
Pracitce #1
[objc] view plain copy// ========= Person.h =========  
@interface Person: NSObject  
{  
}  
-(void) Print;  
@property NSString* name;  
@end  
  
// ========= Person.m =========  
#import "Person.h"  
@implementation Person  
-(void) Print {  
    NSLog(@"Print_Name:%@", _name);    // #100  
}  
@end  
  
// ========= main.mm =========  
#import <Foundation/Foundation.h>  
#import "Person.h"  
  
int main(int argc, const charchar * argv[]) {  
    @autoreleasepool {  
          Person* p = [[Person alloc] init];  
          [p setName:@"Henry"];  
          NSLog(@"Name:%@", [p name]);  
          [p Print];  
    }  
}  

> 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// ========= Person.h =========  
@interface Person: NSObject  
{  
@public  
    NSString* name;     // #200  
}  
-(void) Print;  
@property NSString* name;  
@end  
  
// ========= Person.m =========  
#import "Person.h"  
@implementation Person     // #201  
-(void) Print {  
    NSLog(@"PrintName:%@", name);     // #202  
     NSLog(@"Print_Name:%@", _name);  
}  
@end  
  
// ========= main.mm =========  
#import <Foundation/Foundation.h>  
#import "Person.h"  
  
int main(int argc, const charchar * argv[]) {  
    @autoreleasepool {  
          Person* p = [[Person alloc] init];  
          [p setName:@"Henry"];  
          NSLog(@"Name:%@", [p name]);  
          [p Print];  
    }  
}  

> 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// ========= Person.h =========  
@interface Person: NSObject  
{  
@public  
    NSString* name;  
}  
-(void) Print;  
@property NSString* name;  
@end  
  
// ========= Person.m =========  
#import "Person.h"  
@implementation Person  
@syntheize name = _name;     // #300  
-(void) Print {  
    NSLog(@"PrintName:%@", name);  
     NSLog(@"Print_Name:%@", _name);  
}  
@end  
  
// ========= main.mm =========  
#import <Foundation/Foundation.h>  
#import "Person.h"  
  
int main(int argc, const charchar * argv[]) {  
    @autoreleasepool {  
          Person* p = [[Person alloc] init];  
          [p setName:@"Henry"];  
          NSLog(@"Name:%@", [p name]);  
          [p Print];  
    }  
}  

> 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// ========= Person.h =========  
@interface Person: NSObject  
{  
@public  
    NSString* name;     // #400  
}  
-(void) Print;  
@property NSString* name;  
@end  
  
// ========= Person.m =========  
#import "Person.h"  
@implementation Person  
@syntheize name = name;     // #401  
-(void) Print {  
    NSLog(@"PrintName:%@", name);  
     NSLog(@"Print_Name:%@", _name);     // #402  
}  
@end  
  
// ========= main.mm =========  
#import <Foundation/Foundation.h>  
#import "Person.h"  
  
int main(int argc, const charchar * argv[]) {  
    @autoreleasepool {  
          Person* p = [[Person alloc] init];  
          [p setName:@"Henry"];  
          NSLog(@"Name:%@", [p name]);  
          [p Print];  
    }  
}  

> 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。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: