[Objective-C] property setter/getter via @property

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

环境
Mac OS Yosemite (10.10) + XCode 6.1.1

Pracitce #1

// ========= 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 char * 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

// ========= 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 char * 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

// ========= 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 char * 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

// ========= 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 char * 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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值