您的位置:首页 > 编程语言

obj-c编程02:给类自动合成存取方法

2014-06-28 13:53 309 查看
我们在此篇对obj-c编程01中的Box的例子稍加改动,一是添加的自动合成存取器,二是将Box按照其标准的写法分成3个文件,即头文件Box.h,类实现文件Box.m,以及主文件test.m.

1.Box.h

#import <Foundation/Foundation.h>

@interface Box:NSObject{
int l;
int w;
}
@property int l,w;
-(void)print;
@end


2.Box.m

#import "Box.h"

@implementation Box
@synthesize l,w;

-(void)print{
NSLog(@"l=%d,w=%d",l,w);
}
@end


3.test.m

#import "Box.h"

int main(int argc,char **argv)
{
@autoreleasepool {
NSLog(@"hello class! :)");

Box *box = [[Box alloc] init];
[box setL:100];
[box setW:200];
NSLog(@"look box :");
[box print];
NSLog(@"other way to look box : l=%d,w=%d",[box l],[box w]);
}
return 0;
}


编译命令和执行结果为:

wisy@wisy-ThinkPad-X61:~/src/objc_src/class_std$ clang -O3 -g0 -MMD -MP -DGNUSTEP -DGNUSTEP_BASE_LIBRARY=1 -DGNU_GUI_LIBRARY=1 -DGNU_RUNTIME=1 -DGNUSTEP_BASE_LIBRARY=1 -fno-strict-aliasing -fexceptions -fobjc-exceptions -D_NATIVE_OBJC_EXCEPTIONS -pthread -fPIC -Wall -DGSWARN -DGSDIAGNOSE -Wno-import -g -O2 -fgnu-runtime -fconstant-string-class=NSConstantString -I. -I/home/wisy/GNUstep/Library/Headers -I/usr/local/include/GNUstep -I/usr/include/GNUstep -lobjc -lgnustep-base -o cls_test Box.m test.m
wisy@wisy-ThinkPad-X61:~/src/objc_src/class_std$ ./cls_test2014-06-28 13:53:35.666 cls_test[16916] hello class! :)
2014-06-28 13:53:35.668 cls_test[16916] look box :
2014-06-28 13:53:35.668 cls_test[16916] l=100,w=200
2014-06-28 13:53:35.668 cls_test[16916] other way look box : l=100,w=200


我开始在@interface中没有实例变量的定义,结果编译报错了:

Box.m:4:14: error: synthesized property 'l' must either be named the same as a
compatible instance variable or must explicitly name an instance variable
@synthesize l,w;
^
Box.m:4:16: error: synthesized property 'w' must either be named the same as a
compatible instance variable or must explicitly name an instance variable
@synthesize l,w;


添加上后则正常,原因不明(书上说可以不加).另外要注意的是自动合成的写方法是SetL和SetW,别搞错了.

我们还可以简写读写合成器方法,甚至一般方法如下:

#import "Box.h"

int main(int argc,char **argv)
{
@autoreleasepool {
NSLog(@"hello class! :)");

Box *box = [[Box alloc] init];
[box setL:100];
[box setW:200];

box.l = 101;	//same as [box setL:101]
box.w = 102;	//same as [box setW:102]

NSLog(@"look box :");
[box print];
(void)box.print;	//same as [box print]
NSLog(@"other way to look box : l=%d,w=%d",[box l],[box w]);
NSLog(@"other way to look box : l=%d,w=%d",box.l,box.w); //same as [box l],[box w]
}
return 0;
}


第17行前面加了(void)告诉编译器我不关心print有没有返回,如果不加会有警告:

test.m:17:3: warning: property access result unused - getters should not be
used for side effects [-Wunused-value]
box.print;
^~~~~~~~~


原则上一般方法不用这种方式调用,还是用一般的[ ]为妥哦.

[2014.07.03第1次添加内容]:属性的原子关键字

我们往往可以在源代码中看见如下的写法:

@property(nonatomic,copy)Some_class *obj;

其中copy关键字可以在后面的第11,12篇中得到解答,这里简单说说前者。此处使用nonatomic是为了告诉系统不要使用互斥(mutex)锁来保护属性的存取方法,这在编写单线程的代码中会用的到。如果是在多线程中且需要同步安全,则不能指定nonatomic或者可以指定atomic(默认值)关键字,这时系统可以帮我们自动加上互斥代码保证多线程同步安全喽。

[2014.07.05第1次修改]:nonatomic特性的展开

在使用nonatiomic特性的代码实际中是如何展开的呢?如下:

{

[threadLock lock];

//use val

[threadLock unlock];

}

[2014.07.05第2次添加内容]:属性与同步语法的扩展

在前面介绍的属性和同步语法还有其他的变形形式哦,我们可以在声明属性时只定义读者方法或写者方法,还可以改变读者或写者方法的名字;在后面的同步中,我们还可以改变与属性绑定的实例变量哦:



下面上代码,相信一目了然:

#import<Foundation/Foundation.h>

#define msg(...) NSLog(__VA_ARGS__)

@interface Foo:NSObject{
int _idx;
NSString *_name;
}
@property (getter=idx_r,setter=idx_w:) int idx;
@property (retain)NSString *name;

-(NSString*)description;
@end

@implementation Foo
@synthesize idx=_idx,name=_name;

-(NSString*)description{
return [NSString stringWithFormat:@"_idx:%d,idx:%d,_name:%@,name:%@",\
_idx,self.idx,_name,self.name];
}
@end

int main(int argc, char *argv[]){
@autoreleasepool {
Foo *foo = [[Foo alloc] init];
[foo idx_w:101];
[foo setName:@"helo foo!"];
msg(@"%d %@ %@",[foo idx_r],[foo name],foo.name);
msg(@"%@",foo);
}
return 0;
}


编译运行结果如下:

wisy@wisy-ThinkPad-X61:~/src/objc_src$ clang -objc-arc -O3 -g0 $OBJC_OPTS -lobjc -lgnustep-base -o
1 1.m
wisy@wisy-ThinkPad-X61:~/src/objc_src$ ./1
2014-07-05 10:36:46.143 1[3576] 101 helo foo! helo foo!
2014-07-05 10:36:46.146 1[3576] _idx:101,idx:101,_name:helo foo!,name:helo foo!

其实和@synthesize类似,还有一个同步关键字@dynamic,使用该关键字生成的存取方法要手动写方法哦,这样你对存取方法会有更大的自由度哦!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: