self.a 和 _a 的区别
在OC中我们可以通过指令@property定义属性。
OC对属性封装了许多方法,同时也会自动实现一些方法,相比实例变量,感觉更加面向对象些。
一般定义属性的方法如下,在Class Test中定义属性int a。
@interface Test:NSObject
@property int a;
-(void) changeAValue:(int) newValue;
@end
在类的实例方法中,我们可以用下面两种方式来访问a属性:
1、直接用属性名访问:
-(void) changeAValue:(int) newValue
{
_a = newValue; // 默认生成的属性成员变量前面会自动加上“_”前缀
}
2、通过self.a的形式访问
-(void) changeAValue:(int) newValue
{
self.a = newValue;
}
这两种访问方式有区别吗?答案是肯定的。
通过第一种方式访问,其实是类似于C++的访问方式,是直接访问的实例变量并赋值。而第二种方式,并不像其表面那么直观,它其实是通过调用编译器自动生成的对于a变量的赋值函数来实现的。即
-(void) changeAValue:(int) newValue
{
self.a = newValue; // 此处实际是调用 [self setA:newValue];
}
个人感觉在类中调用自身的属性,还是用self.a的形式比较好。因为它封装了访问方法,加强了我们对变量的控制,也更面向对象些。
为了说明self.a的形式更好用一点,我们可以举个例子。在Class Test中,再添加对象属性NSString* b,并指明其为一个深拷贝属性。
@interface Test:NSObject
@property int a;
@property(copy) NSString* b, *c;
-(void) changeAValue:(int) newValue;
-(void) changeBValue:(NSString*) newBValue andCValue:(NSString*) newCValue;
@end
添加实例方法changeBValue:andCValue
-(void) changeBValue:(NSString*) newBValue andCValue:(NSString*) newCValue
{
self.b = newBValue;
_c = newCValue;
}
在mian函数中写测试用例:
int main(int argc, const char * argv[]) {
@autoreleasepool {
Test* testObj = [[Test alloc] init];
NSMutableString* newBValue = [NSMutableString stringWithString:@"Tom"];
NSMutableString* newCValue = [NSMutableString stringWithString:@"www3@126.com"];
[testObj setBValue:<span style="font-family: Arial, Helvetica, sans-serif;">newBValue </span>andCValue:newCValue];
NSLog(@"The value of b is %@ and c is %@", testObj.b, testObj.c);
[name appendString:@"andLily"];
[email appendString:@"andLily"];
NSLog(@"The value of b is %@ and c is %@", testObj.b, testObj.c);
}
return 0;
}
运行,得到结果为
可以看到,b的值仍然是Tom,而c的值已经跟随这newCValue的值做了改变,末尾添加了“andLily”字符串。
我们的原意是对类属性的赋值应当是深拷贝赋值(在@property声明中添加了copy关键字),但现在b是深拷贝,而c仍然是默认的浅拷贝。究其原因,就是因为一个调用了self来访问,另一个直接对类属性进行了访问。在调用self的赋值方法访问时,编译器会自动根据copy关键字生成对应的深拷贝赋值函数,其实现类似于:
-(void) setB:NSString* newValue
{
if ( _b! = newValue)
{
_b = [newValue copy];
}
}
b已经和外部不指向同一块内存,因此b的值没有随着外部而改变。
从上面的例子可以看出,我们在类中,应该尽量使用self.a的形式来访问属性,这样对属性的访问会更加可靠简单,否则就需要我们自己实现对应属性的存取方法。
关于类的属性,还有下面几点要注意:
1、类的属性仅在本类中可以访问,子类无法通过_a的形式访问。但是可以通过继承父类的存取方法访问。
2、当声明类的属性后,编译器会自动生成对应的存取方法,但是我们仍然可以通过重写的方式,阻止编译器自动为我们生成存取方法,而是使用我们自己定义的存取方法。
self.a 和 _a 的区别的更多相关文章
- C语言数组和指针的理解_在取地址运算上的操作_指针加减操作_a 和&a 的区别
1.一个实例+理论分析 在了解数组和指针的访问方式前提下,下面再看这个例子: main() { int a[5]={1,2,3,4,5}; int *ptr=(int *)(&a+1); pr ...
- Objective-C 中self.与_访问方式的区别
Objective-C中属性self.a与_a访问的区别: 在OC中我们可以通过指令@property定义属性. OC对属性封装了许多方法,同时也会自动实现一些方法,相比实例变量,感觉更加面向对象些. ...
- c++ list, vector, map, set 区别与用法比较
http://blog.csdn.net/alex_xhl/article/details/37692297 List封装了链表,Vector封装了数组, list和vector得最主要的区别在于ve ...
- Python第二天 变量 运算符与表达式 input()与raw_input()区别 字符编码 python转义符 字符串格式化 format函数字符串格式化 帮助
Python第二天 变量 运算符与表达式 input()与raw_input()区别 字符编码 python转义符 字符串格式化 format函数字符串格式化 帮助 目录 Pychar ...
- iOS学习——@class和#import、#include的区别
在iOS开发过程中,我们在一些源码中经常会看到导包的时候有的用#import进行导包,但是有的的时候也会看到用@class进行导包,那么这两种方式有什么区别呢? 一 @class和#import的主要 ...
- 【SQL】glob 和 like 的区别
LIKE 和 GLOB 都可以用来匹配通配符指定模式的文本值.如果搜索表达式与模式表达式匹配,LIKE 运算符将返回真(true),也就是 1 区别: (1)使用的通配符不一样 like: 百分号( ...
- var和const和let的区别
简述: 1.前端的变量申明,可以用到var,ES6的const(衡量)/let(变量) 2.在ES5用的都是var,到ES6之后,也就是2015年开始出现const/let. var 不会报错,有声明 ...
- C++浅拷贝和深拷贝的区别
C++浅拷贝和深拷贝的区别 2012-04-24 21:22 11454人阅读 评论(6) 收藏 举报 c++deleteclass编译器c c++默认的拷贝构造函数是浅拷贝 浅拷贝就是对象的数据成员 ...
- list, vector, map, set 区别与用法比较
List封装了链表,Vector封装了数组, list和vector得最主要的区别在于vector使用连续内存存储的,他支持[]运算符,而list是以链表形式实现的,不支持[]. Vector对于随机 ...
随机推荐
- hdu2067
如果i==j&&j-1>=0时候,f[i][j]=f[i][j-1]; 如果j==0时候,f[i][j]=1; 其他 f[i][j]=f[i-1][j]+f[i][j-1]; # ...
- Android IOS WebRTC 音视频开发总结(四八)-- 从商业和技术的角度看视频行业的机会
本文主要从不同角度介绍视频行业的机会,文章来自博客园RTC.Blacker,支持原创,转载必须说明出处,欢迎关注个人微信公众号blacker ----------------------------- ...
- javaSE第二十三天
第二十三天 338 1.进程和线程的概述 338 2.多线程(理解) 339 (1)多线程:一个应用程序有多条执行路径 339 (2)Java程序的运行原理及JVM的启动是多线 ...
- CentOS6.5 python 2.6升级到2.7
在CentOS6.5下,将自带的python2.6.6升级到python2.7.3,解决方法如下: 下载python2.7.3包,并解压缩,输入命令:#wget http://python.org/f ...
- 取得Android平台某设备上所有可用的Sensors
本来要写一个检测手机的温度的小应用,学习一下传感器的api,可结果怎么写不行.经检测,发现取得的Sensor为NULL,这才明白,我手机没有TYPE_AMBIENT_TEMPERATURE传感器. 于 ...
- MySQL连接语法
http://www.cnblogs.com/hanzhaoxin/p/3590642.html 内连接:INNER JOIN 内连接为 两个表中必须都同时满足条件 内连接,即最常见的等值连接自然连 ...
- PHP用Array模拟枚举
C#中枚举Enum的写法: /// <summary> /// 公开类型 2-好友可见 1-公开 0-不公开 /// </summary> public enum OpenSt ...
- PHP preg_replace() 正则替换所有符合条件的字符串示例
PHP preg_replace() 正则替换,与Javascript 正则替换不同,PHP preg_replace() 默认就是替换所有符号匹配条件的元素. 需要用程序处理的数据并不总是预先以数 ...
- C语言-sizeof()与strlen()的区别【转】
先看看sizeof() 一.sizeof的概念 sizeof是C语言的一种单目操作符,如C语言的其他操作符++.--等.它并不是函数.sizeof操作符以字节形式给出了其操作数的存储大小.操作数可以是 ...
- Treeview获取父节点
private void treeView1_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object&g ...