Code:
#import <Foundation/Foundation.h>
/****************************************
* Person类
****************************************/
// 要采用某个协议,需要在类的声明中列出该协议的名称,并用尖括号括起来
// 同时采用多个协议,则在协议的名称之间用逗号分割,如:<NSCopying, NSCoding>
// 可以按任意顺序列出多个协议
@interface Person : NSObject <NSCopying>
@property (nonatomic, copy, readwrite) NSString* name;
@end
@implementation Person
// copyWithZone:方法的返回类型为id,参数类型为NSZone
- (id)copyWithZone:(NSZone*)zone {
// 通过使用[self class],allocWithZone:消息将会被发送给正在接受copy消息的对象所属的类
// 这个类可能是copyWithZone:消息所在类的子类,通过这种方式可以正确的创建想要的对象
// 如果不使用[self class],而使用具体的类名,可能导致创建得到的实例无法返回给类型正确的实例指针
// allocWithZone:方法是一个类方法,其最后一行返回新创建的实例
// zone是NSZone类的一个实例,指向一块可供分配的内存区域
Person* personCopy = [[[self class] allocWithZone:zone] init];
// 复制实例变量或属性
[personCopy setName:[self name]];
// 返回新创建的对象
return personCopy;
}
- (NSString*)description {
return [NSString stringWithFormat:@"[name = %@]", [self name]];
}
- (void)dealloc {
[[self name] release];
[super dealloc];
}
@end
/****************************************
* GoodPerson类
****************************************/
// 父类采用了某个协议,其子类也将遵守该协议,无需用不必要的代码说明
@interface GoodPerson : Person
@property (nonatomic, assign, readwrite) NSUInteger age;
@end
@implementation GoodPerson
- (id)copyWithZone:(NSZone*)zone {
// 由于父类已经实现了copyWithZone:方法
// 子类只需调用该方法,并完成属于自己需要负责的那部分复制操作即可
GoodPerson* goodPersonCopy = [super copyWithZone:zone];
[goodPersonCopy setAge:[self age]];
return goodPersonCopy;
}
- (NSString*)description {
return [NSString stringWithFormat:@"[name = %@, age = %lu]", [self name], [self age]];
}
@end
/****************************************
* main函数
****************************************/
int main(int argc, const char * argv[]) {
Person* p1 = [[Person alloc] init];
[p1 setName:@"AAA"];
// 当向一个实例发送copy消息时,则该copy消息会被转换为调用copyWithZone:方法
Person* p2 = [p1 copy];
NSLog(@"Address(p1) = %p, retainCount(p1) = %lu", p1, [p1 retainCount]);
NSLog(@"Address(p2) = %p, retainCount(p2) = %lu", p2, [p2 retainCount]);
NSLog(@"p1%@", p1);
NSLog(@"p2%@", p2);
[p1 release];
[p2 release];
GoodPerson* gp1 = [[GoodPerson alloc] init];
[gp1 setName:@"BBB"];
[gp1 setAge:20];
GoodPerson* gp2 = [gp1 copy];
NSLog(@"Address(gp1) = %p, retainCount(gp1) = %lu", gp1, [gp1 retainCount]);
NSLog(@"Address(gp2) = %p, retainCount(gp2) = %lu", gp2, [gp2 retainCount]);
NSLog(@"gp1%@", gp1);
NSLog(@"gp2%@", gp2);
[gp1 release];
[gp2 release];
return 0;
}
Output:
Address(p1) = 0x1002021b0, retainCount(p1) = 1
Address(p2) = 0x1002021c0, retainCount(p2) = 1
p1[name = AAA]
p2[name = AAA]
Address(gp1) = 0x100205170, retainCount(gp1) = 1
Address(gp2) = 0x1002053d0, retainCount(gp2) = 1
gp1[name = BBB, age = 20]
gp2[name = BBB, age = 20]