閱讀127 返回首頁    go 阿裏雲 go 技術社區[雲棲]


obj-c編程02:給類自動合成存取方法

    我們在此篇對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,使用該關鍵字生成的存取方法要手動寫方法哦,這樣你對存取方法會有更大的自由度哦!

最後更新:2017-04-03 06:03:10

  上一篇:go Swift方法
  下一篇:go (多)繼承中的構造與析構