11 复制对象 [Objective-C基础教程]

11.1首先回顾继承部分
//***********************************************************************************************//
//XYPoint类声明
#import<Foundation/Foundation.h>
@interfaceXYPoint:NSObject
{
intx;
inty;
}
@propertyintx,y; //存取器属性
-(void)setX:(int)xValandY:(int)yVal;
@end
//***********************************************************************************************//
//***********************************************************************************************//

//XYPoint类定义
#import"XYPoint.h"
@implementationXYPoint
@synthesizex,y;
-(void)setX:(int)xValandY:(int)yVal
{
x=xVal;
y=yVal;
}
@end
//***********************************************************************************************//
//***********************************************************************************************//
//Rectangle类声明
#import<Foundation/Foundation.h>

@classXYPoint;
@interfaceRectangle:NSObject
{
intwidth;
intheight;
XYPoint*origin;
}
@propertyintwidth,height; // 存取器属性
-(XYPoint*)origin;
-(void)setOrigin:(XYPoint*)pt;
-(void)setWidth:(int)wandHeight:(int)h;
-(int)area;
-(int)perimeter;
@end
//***********************************************************************************************//
//***********************************************************************************************//

//Rectangle类定义
#import"Rectangle.h"
@implementationRectangle
@synthesizewidth,height;
-(void)setWidth:(int)wandHeight:(int)h
{
width=w;
height=h;
}
-(void)setOrigin:(XYPoint*)pt
{
origin=pt;
}
-(int)area
{returnwidth*height;
}
-(int)perimeter
{
return(width+height)*2;
}
-(XYPoint*)origin
{
returnorigin;
}
@end
//***********************************************************************************************//
//***********************************************************************************************//
#import"Rectangle.h"
#import"XYPoint.h"

intmain(intargc,char*argv[])
{
NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init];
Rectangle*myRect=[[Rectanglealloc]init];
[myRectsetWidth:5andHeight:8];
XYPoint*myPoint=[[XYPointalloc]init];
[myPointsetX:100andY:200];
myRect.origin=myPoint; //赋值
NSLog(@"Originat(%i,%i)",myRect.origin.x,myRect.origin.y);
[myPointsetX:50andY:50];
NSLog(@"Originat(%i,%i)",myRect.origin.x,myRect.origin.y);
[myRectrelease];
[myPointrelease];
[pooldrain];
return0;
}

//***********************************************************************************************//
myRect.origin = myPoint;
这样赋值的结果仅仅是将对象myPoint的地址复制到myRect.origin中。在赋值操作结束时,两个变量
都指向内存中的同一个地址。
所以,将一个变量赋值给另一个对象仅仅是创建另一个对这个对象的引用。如果dataArray和dataArray2
都是NSMutableArray对象,那么语句
dataArray2 = dataArray;
[dataArray2 removeObjectAtIndex:0];
将从这两个变量引用的同一个数组中删除第一个元素。
//***********************************************************************************************//
#import<Foundation/NSObject.h>
#import<Foundation/NSArray.h>
#import<Foundation/NSString.h>
#import<Foundation/NSAutoreleasePool.h>
intmain(intargc,char*argv[])
{NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init];
NSMutableArray*dataArray=[NSMutableArrayarrayWithObjects:
@"one",@"two",@"three",@"four",nil];
NSMutableArray*dataArray2;
dataArray2=dataArray;
[dataArray2 removeObjectAtIndex:0];
NSLog(@"dataArray:");
for(NSString*elemindataArray)
NSLog(@"%@",elem);
NSLog(@"dataArray2:");
for(NSString*elemindataArray2)
NSLog(@"%@",elem);

//以下输出结果是:
// dataArray:
// two
// three
// four
// dataArray2:
// two
// three
// four
//下面开始Copy
dataArray2=[dataArraymutableCopy];
[dataArray2 removeObjectAtIndex:0];
NSLog(@"dataArray:");
for(NSString*elemindataArray)
NSLog(@"%@",elem);
NSLog(@"dataArray2:");
for(NSString*elemindataArray2)
NSLog(@"%@",elem);
//以下输出结果是:

// dataArray:
// two
// three
// four
//
// dataArray2:
// three
// four
[dataArray2release];
[pooldrain];
return0;
}

//***********************************************************************************************//

11.2copy和mutableCopy
利用名为copy和mutableCopy的方法,可以创建对象的副本。结合NSMutableArray对象dataArray
和dataArray2,语句
dataArray2=[dataArraymutableCopy];
在内存中创建了一个新的dataArray副本,并复制了它的所有元素。随后,执行语句 [dataArray2
removeObjectAtIndex:0];
删除了dataArray2中的第一个元素,但是不会删除dataArray中的。
注意:
A、产生一个对象的可变副本并不要求被复制的对象本身是可变的。也可以创建可变对象的不可
变副本。
B、在产生数组的副本时,数组中每个元素的保持计数将通过复制操作自动增1。所以,需要
[dataArray2release]; 释放它的内存。

11.3 浅复制和深复制
浅复制代码分析:
//***********************************************************************************************//
#import<Foundation/NSObject.h>
#import<Foundation/NSArray.h>
#import<Foundation/NSString.h>
#import<Foundation/NSAutoreleasePool.h>
intmain(intargc,char*argv[])
{
NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init];
NSMutableArray*dataArray=[NSMutableArrayarrayWithObjects:
[NSMutableStringstringWithstring:@"one"],
[NSMutableStringstringWithstring:@"two"],
[NSMutableStringstringWithstring:@"three"],
nil
];

NSMutableArray*dataArray2;
NSMutableString*mStr;
NSLog(@"dataArray:");
for(NSString*elemindataArray)
NSLog(@"%@",elem);
//输出结果:
// dataArray:
// one
// two
// three
dataArray2=[dataArraymutableCopy];
mStr=[dataArray objectAtIndex:0]; //检索dataArray的第一个元素
[mStr appendString:@"ONE"]; //将字符串附加到这个元素
NSLog(@"dataArray:");
for(NSString*elemindataArray)
NSLog(@"%@",elem);
NSLog(@"dataArray2:");
for(NSString*elemindataArray2)
NSLog(@"%@",elem);
//以下输出结果是:

// dataArray:
// oneONE
// two
// three
// dataArray2:
// oneONE
// two
// three
[dataArray2release];
[pooldrain];

return0;
}
//***********************************************************************************************//
dataArray的第一元素发生改变:从集合中获取元素时,得到了这个元素的一个新引用,但并不是一个
新副本。所以,对dataArray调用objectAtIndex:方法时,返回的对象与dataArray中的第一个元素都指向
内存中的同一个对象。随后,修改string对象的mStr的副作用就是同时改变了dataArray的第一个元素。
dataArray2的第一元素发生改变:这与默认的浅复制方式有关。使用mutableCopy方法复制数组时,
在内存中为新的数组对象分配了空间,并且将单个元素复制到新数组中。但是,这仅仅是将一个数组的元
素复制到另一个数组。那么,这两个数组中的每个元素指向内存中的同一个字符串。这与将一个对象复制
给另一个对象没有什么区别。
要为数组中每个元素创建完全不同的副本,需要执行所谓的深复制,也就是要创建数组中的每个对象
内容的副本。例如,假设想要更改上面dataArray2的第一个元素,但是不更改dataArray的第一个元素,
可以创建一个新字符串,并将它存储到dataArray2的第一个位置,如下所示:
mStr=[NSMutableString stringWithstring: [dataArray2 objectAtIndex:0]];
然后,可以更改mStr,并使用replaceObjectAtIndex:withObject:方法将它添加到数组中,如下所示:
[mStr appendString @”ONE”];
[dataArray2 replaceObjectAtIndex:0 withObject:mStr];
这样,替换数组中的对象后,mStr和dataArray2的第一个元素仍指向内存中的同一个对象。这意味着
随后在程序中对mStr做的修改也将更改数组的第一个元素。

来源://作者:/更新时间:2015-05-25
相关文章
评论:
验证码:
匿名评论:

最新文章

新热推荐

文章排行