【OC学习-26】对象的浅拷贝和深拷贝——关键在于属性是否可被拷贝
2014-09-08 13:44
337 查看
对象的拷贝分为浅拷贝和深拷贝,浅拷贝就是只拷贝对象,但是属性不拷贝,拷贝出来的对象和原来的对象共用属性,即指向同一个属性地址,深拷贝则相当于不仅拷贝了一个对象还拷贝了它的属性,即完全是两个东西,只不过内容相同而已。
拷贝用到协议,如果这个类创建对象后,这个对象要被拷贝,那么这个类就需要用到拷贝协议,分两种:<NSCopying>和<NSMutableCopying>相当于一个是拷贝,另一个是拷贝后可修改。
(1)浅拷贝的案例。有一个Person类,它创建一个person1对象后,用person1再拷贝一个person2出来。
//Person类的Person.h文件
#import <Foundation/Foundation.h>
//因为这个类要支持拷贝,所以需要引入拷贝协议,有两种,后一种拷贝后可修改
@interface Person : NSObject<NSCopying,NSMutableCopying>
@property(nonatomic,copy) NSString* name;
@property(nonatomic,retain) NSNumber* age;
@end
结果:
0x1002036f0,0x100200330 //不同
0x1227,0x1227 //相同
(2)深拷贝的案例。
按道理是只需要把Person.m里面的赋值语句改成下面的样子,就能实现深拷贝:
person.name=[_name copy];
person.age=[_age copy];
但是,因为cocoa优化过了,所以有如下规则:
a:如果是Foundation框架里地不可变对象,就是Array,NSString等创建的对象,直接用copy来拷贝相当于retain,也就是属性还是同一个;
b:如果是用mutableCopy来拷贝,不管是可变还是不可变对象,属性神马的都直接拷贝了一份,即真正意义上得拷贝,它拷贝出来的对象统统都是可变的;
c:如果是可变对象,我们用copy也能实现真正意义上的拷贝,但是拷贝出来的对象是不可变的。
所以,我们拿name实验(因为age没有mutableCopy)实现语句的修改:
person.name=[_name mutableCopy]
person.age=[_age copy];
然后再输出person1和person2的name属性的地址,发现就不同了。
总结:
浅拷贝和深拷贝在实际项目中不常用,可以做一般了解。
拷贝用到协议,如果这个类创建对象后,这个对象要被拷贝,那么这个类就需要用到拷贝协议,分两种:<NSCopying>和<NSMutableCopying>相当于一个是拷贝,另一个是拷贝后可修改。
(1)浅拷贝的案例。有一个Person类,它创建一个person1对象后,用person1再拷贝一个person2出来。
//Person类的Person.h文件
#import <Foundation/Foundation.h>
//因为这个类要支持拷贝,所以需要引入拷贝协议,有两种,后一种拷贝后可修改
@interface Person : NSObject<NSCopying,NSMutableCopying>
@property(nonatomic,copy) NSString* name;
@property(nonatomic,retain) NSNumber* age;
@end
//这是Person.m文件 #import "Person.h" @implementation Person //这是系统函数,可以直接拷贝过来 - (id)copyWithZone:(NSZone *)zone{ Person *person=[[[self class]allocWithZone:zone]init]; //默认格式 person.name=_name; //浅拷贝就是直接赋值即可 person.age=_age; //浅拷贝就是直接赋值即可 return person; } @end
//main.m文件 #import <Foundation/Foundation.h> #import "Person.h"//记得引入头文件 int main(int argc, const char * argv[]) { @autoreleasepool { Person *person1=[[Person alloc]init]; person1.name=@"jack"; person1.age=@18; Person *person2=[person1 copy]; NSLog(@"%p,%p",person1,person2);//输入两个对象地址,不同 NSLog(@"%p,%p",person1.age,person2.age);//输出两个对象的属性地址,相同 } return 0; }
结果:
0x1002036f0,0x100200330 //不同
0x1227,0x1227 //相同
(2)深拷贝的案例。
按道理是只需要把Person.m里面的赋值语句改成下面的样子,就能实现深拷贝:
person.name=[_name copy];
person.age=[_age copy];
但是,因为cocoa优化过了,所以有如下规则:
a:如果是Foundation框架里地不可变对象,就是Array,NSString等创建的对象,直接用copy来拷贝相当于retain,也就是属性还是同一个;
b:如果是用mutableCopy来拷贝,不管是可变还是不可变对象,属性神马的都直接拷贝了一份,即真正意义上得拷贝,它拷贝出来的对象统统都是可变的;
c:如果是可变对象,我们用copy也能实现真正意义上的拷贝,但是拷贝出来的对象是不可变的。
所以,我们拿name实验(因为age没有mutableCopy)实现语句的修改:
person.name=[_name mutableCopy]
person.age=[_age copy];
然后再输出person1和person2的name属性的地址,发现就不同了。
总结:
浅拷贝和深拷贝在实际项目中不常用,可以做一般了解。
相关文章推荐
- OC学习篇之---对象的拷贝
- 访问form对象的关键属性和方法【学习笔记】
- 18--26 面向对象程序设计20(属性是否在对象(和原型对象)中)
- 【OC学习-31】利用KVC即键值编码来访问一些对象的属性,尽管这些属性是私有的
- OC学习篇之---对象的拷贝
- 【OC学习-32】KVO-用一个对象监控另一个对象的属性,如有变化,则输出需要的结果
- 【OC学习-15】如何判断两个对象是否属于同一个类?如何判断一个对象是否属于某一个类?
- as3对象销毁是否需要全部属性置null?
- 比较两个对象相等、克隆 、是否允许实例化继承 CLR学习第六课
- 学习笔记---页面对象的11个事件, 其中InitComplete-PreLoad之间和Load-LoadComplete之间的时间点, 很关键
- delphi 中判断对象是否具备某一属性
- 判断JS对象是否拥有某属性
- ASP.NET学习资料四 Page对象中不可遗忘的属性
- Struts2 用 s:if test 判断String类型的对象属性值和单字符是否相等的问题
- JavaScript学习点滴—js对象的四种类型的属性、方法的访问
- WPF学习旅程(三)——在XAML中为对象的属性赋值
- ASP.NET 3.5核心编程学习笔记(26):HttpApplication对象
- 对象属性拷贝(全匹配拷贝)
- Ruby 学习四 (类、对象和变量二 类的继承和属性)
- 动态判定Groovy对象方法和属性是否存在