人们常常会读到,不可变类可以通过以下方式非常有效地实现copyWithZone:
- (id) copyWithZone:(NSZone*)zone { return [self retain]; }
实施背后的想法是显而易见的:
原始和副本都是不可变的实例,它们将始终具有完全相同的内容,因此,为什么不通过保留原始文件来指向同一存储,并避免复制的开销.
但是,如果存在可变子类会发生什么?
使用干净的体系结构,子类不必关心其基类的实现细节,可变子类应该可以通过这种方式实现copyWithZone:
- (id) copyWithZone:(NSZone*)zone { MyClass* myCopy = [super copyWithZone:zone]; myCopy->myMember = [myMember copyWithZone:zone]; return myCopy; }
但这对于copyWithZone的上述超类实现意味着什么呢?
子类是可变的,所以虽然副本仍然是不可变的,但是原来现在是可变的,但是由于超类实现的子类copyWithZone在自身的保留实例上运行:self和myCopy都指向同一个实例,所以如果我以后更改mutableOriginal.myMember的值,然后这也将更改immutableCopy.myMember,这是完全错误的.
那么不可变的类应该以下面的方式更好地实现copyWithZone?
- (id) copyWithZone:(NSZone*)zone { if([[self class] isMemberOfClass:[MyBaseClass class]]) return [self retain]; else { MyBaseClass* myCopy = [[self alloc] init]; myCopy->myBaseMember = [myBaseMember copyWithZone:zone]; return myCopy; } }