我们在此篇对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,使用该关键字生成的存取方法要手动写方法哦,这样你对存取方法会有更大的自由度哦!

obj-c编程02:给类自动合成存取方法的更多相关文章

  1. Python编程-面向对象和类

    一.面向对象的程序设计 1.面向过程 VS 面向对象 (1)编程范式 编程是程序员用特定的语法+数据结构+算法组成的代码来告诉计算机如何执行任务的过程,一个程序是程序员为了得到一个任务结果而编写的一组 ...

  2. [.net 面向对象编程基础] (9) 类和类的实例

    [.net 面向对象编程基础] (9) 类和类的实例 类 ,顾名思义就是分类.类别的意思.我们要面向对象编程,就需要对不同的事物进行分类.类可以说是.net面向对象的核心. 类:就是具有相同的属性和功 ...

  3. 编程实现Windows系统自动登录

    编程实现Windows系统自动登录 原理: 通过注册表修改实现.Windows内置了自动登录的机制,在登录系统时,winlogon会检查注册表下有没有设置自动登录,如果设置了就上就会读取用户名和密码, ...

  4. PHP设计模式:类自动载入、PSR-0规范、链式操作、11种面向对象设计模式实现和使用、OOP的基本原则和自动加载配置

    一.类自动载入 SPL函数 (standard php librarys) 类自动载入,尽管 __autoload() 函数也能自动加载类和接口,但更建议使用 spl_autoload_registe ...

  5. 《挑战30天C++入门极限》C++面向对象编程入门:类(class)

        C++面向对象编程入门:类(class) 上两篇内容我们着重说了结构体相关知识的操作. 以后的内容我们将逐步完全以c++作为主体了,这也意味着我们的教程正式进入面向对象的编程了. 前面的教程我 ...

  6. 并发编程--Concurrent-工具类介绍

    并发编程--Concurrent-工具类介绍 并发编程--Concurrent-工具类介绍 CountDownLatch CylicBarrier Semaphore Condition 对象监视器下 ...

  7. python并发编程02 /多进程、进程的创建、进程PID、join方法、进程对象属性、守护进程

    python并发编程02 /多进程.进程的创建.进程PID.join方法.进程对象属性.守护进程 目录 python并发编程02 /多进程.进程的创建.进程PID.join方法.进程对象属性.守护进程 ...

  8. day40-网络编程02

    Java网络编程02 4.TCP网络通信编程 基本介绍 基于客户端--服务端的网络通信 底层使用的是TCP/IP协议 应用场景举例:客户端发送数据,服务端接收并显示控制台 基于Scoket的TCP编程 ...

  9. Java并发编程:Thread类的使用

    Java并发编程:Thread类的使用 在前面2篇文章分别讲到了线程和进程的由来.以及如何在Java中怎么创建线程和进程.今天我们来学习一下Thread类,在学习Thread类之前,先介绍与线程相关知 ...

随机推荐

  1. [ExtJS5学习笔记]第二十一节 Extjs5中使用config配置给ext.widget或者create方法传递参数

    本文地址:http://blog.csdn.net/sushengmiyan/article/details/39252805 官方例子:http://docs.sencha.com/extjs/5. ...

  2. Android开发学习之路--RxAndroid之初体验

    学了一段时间android,看了部分的项目代码,然后想想老是学基础也够枯燥乏味的,那么就来学习学习新东西吧,相信很多学java的都听说过RxJava,那么android下也有RxAndroid. Rx ...

  3. 1068. Find More Coins (30)

    题目如下: Eva loves to collect coins from all over the universe, including some other planets like Mars. ...

  4. redhat安装vsftpd

    一个小问题 rpm -qa|ftp 但是出现3个ftp 只安装了一个 关于网卡ip 首先,我们看到 网卡上面有个x 说明网络是有问题的 我们双击,看到 我们先把connected和connect at ...

  5. AngularJS进阶(四十)创建模块、服务

    AngularJS进阶(四十)创建模块.服务 学习要点 使用模块构架应用 创建和使用服务 为什么要使用和创建服务与模块? 服务允许你打包可重用的功能,使之能在此应用中使用. 模块允许你打包可重用的功能 ...

  6. printf函数压栈解惑

    最近看到一些程序员的笔试题目,经常会考到printf函数的参数压栈问题,总体来讲就是参数从右向左依次压栈,再出栈,但是今天看到一个看似很简单的题目,却一直找不到头绪.题目如下: #include &l ...

  7. EBS条形码打印

    Oracle  提供两种方式实现 128 码的编码 第一种方式是使用 Reports Builder 实现对 128 码编码, 在 Metalink 305090.1[1]  有 比较详尽的描述,其中 ...

  8. C++ Primer 有感(异常处理)(四)

    查看普通函数的声明的时候,不可能知道该函数会抛出什么异常,但是在捕获异常的时候要知道一个函数会抛出什么样的异常,以便捕获异常. 异常说明:指定,如果函数抛出异常,抛出的异常将是包含在该说明中的一种,或 ...

  9. Android的内存分配与回收

    想写一篇关于android的内存分配和回收文章的想法来源于追查一个魅族手机图片滑动卡顿问题,我们想了很多办法还是没有避免他不停的GC,所以就打算详细的看看内存分配和GC的原理,为什么会不断的GC,GC ...

  10. 11_Eclipse中演示Git版本的创建,历史版本的修改,创建分支,合并历史版本和当前版本

     1 执行以下案例: 某研发团队2011年初开发了一款名为Apollo的信息系统,目前已发布v1.0版本.此项目初期已有部分基础代码, 研发团队再此基础代码上经过3个月的努力发布了一个功能相对完备 ...