---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------
关于对象的浅复制与深复制
浅复制(shallow copy):不会复制所引用的对象,新复制的对象只会指向现有的引用对象。当复制一个NSArray类的对象时,复制的对象只会复制指向引用对象的指针,而不会复制引用对象本身。如果复制了一个包含5个NSString对象的NSArray对象,你最终得到的时5个可供程序使用的字符串对象,而不是10个。
深复制(deep copy):将复制所有的引用对象。如果NSArray的copy方法是深层复制,则在操作完成后得到10个字符串对象。
创建对象的副本
假设我们有一个Engine类。为了能够复制engine对象,Engine类需要采用NSCopying协议。下面是Engine类的新接口:
@interface Engine: NSObject <NSCopying>
@end
因为Engine类采用了NSCopying协议,所以我们必须实现copyWithZone:方法(关于NSCopying协议,上一篇博文已做了简单介绍)。zone是NSZ one类的一个对象,指向一块可供分配的内存区域。当你向一个对象发送copy消息时,该copy消息在到达你的代码前会被转换为copyWithZone:方法。
Engine类的copyWithZone:方法的实现如下:
@implementation Engine:
- (id) copyWithZone: (NSZone *)zone
{
Engine *engineCopy;
engineCopy = [[[self class] allocWithZone: zone] init];
return engineCopy;
} // copyWithZone
由于Engine类没有实例变量,因此我们必须创建一个新的engine对象。copyWithZone:方法的首要任务是获得self参数所属得类,然后向self对象所属得类发送copyWithZone:消息,以分配内存并创建一个该类得新对象。最后,copyWithZone:方法给这个新对象发送allocWithZone:消息使其初始化。
由于allocWithZone:方法是一个类方法。我们需要发消息给一个类。在这里是Engine类。为什么不像下面这样写:
[Engine allocWithZone: zone];
因为,这行代码只适用于Engine类。如果我们创建了Engine类的子类。这就会变的的不适用了。所以我们应该通过[self class]获得当前这个类。
这个实例的完整代码如下:
Engine.h
#import <Cocoa/Cocoa.h>
@interface Engine : NSObject <NSCopying>
@end // Engine
Engine.m
#import "Engine.h"
@implementation Engine
- (id) copyWithZone: (NSZone *) zone
{
Engine *engineCopy;
engineCopy = [[[self class] allocWithZone: zone] init];
return (engineCopy);
} // copyWithZone
- (NSString *) description
{
return (@"I am an engine. Vrooom!");
} // description
@end // Engine
main.m
#import <Foundation/Foundation.h>
#import "Engine.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
Engine *engine = [[Engine alloc] init];
NSLog(@"%@", engine);
Engine *engineCopy = [engine copy];
NSLog(@"%@", engineCopy);
}
return 0;
}
运行后,结果如下:
---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------