对于具有可变子类的不可变类,在 copyWithZone 中返回 [self retain] 真的安全/一个好主意吗? [英] Is returning [self retain] in copyWithZone for immutable classes with mutable subclasses really safe / a good idea?

查看:58
本文介绍了对于具有可变子类的不可变类,在 copyWithZone 中返回 [self retain] 真的安全/一个好主意吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

人们经常读到,不可变类可以通过以下方式非常有效地实现 copyWithZone:

One often reads, that immutable classes can implement copyWithZone very efficiently in the following way:

- (id) copyWithZone:(NSZone*)zone
{
    return [self retain];
}

该实现背后的想法很明显:原件和副本都是不可变的实例,它们总是具有完全相同的内容,所以为什么不通过保留原件来让两者指向相同的存储并避免复制的开销.

The idea behind that implementation is obvious: The original and the copy are both immutable instances and they will always have exactly the same content, so why not let both point to the same storage by retaining the original and avoid the overhead of copying.

然而,如果有一个可变的子类会发生什么?在干净的架构中,子类不必关心其基类的实现细节,可变子类应该可以通过这种方式实现 copyWithZone:

However, what will happen if there is a mutable subclass? With a clean architecture, where a subclass does not have to care about implementation details of its base class, the mutable subclass should be fine to implement copyWithZone in this way:

- (id) copyWithZone:(NSZone*)zone
{
    MyClass* myCopy = [super copyWithZone:zone];
    myCopy->myMember = [myMember copyWithZone:zone];
    return myCopy;
}

但这对于上面 copyWithZone 的超类实现意味着什么?子类是可变的,所以虽然副本仍然是不可变的,原来的现在是可变的,但是由于超类的实现,子类 copyWithZone 对自身的一个保留实例进行操作:self 和 myCopy 都指向同一个实例,所以如果我以后改变 mutableOriginal.myMember 的值,那么它也会改变 immutableCopy.myMember,这是完全错误的.

But what does this mean with the above superclass implementation of copyWithZone? The subclass is mutable, so although the copy still is immutable, the original now is mutable, but the subclass copyWithZone thanks to the superclass implementation operates on a retained instance of itself: self and myCopy both point the the same instance, so if I later change the value of mutableOriginal.myMember, then that will also change immutableCopy.myMember, which is just plain wrong.

那么不可变类不应该​​通过以下方式更好地实现 copyWithZone 吗?

So shouldn't immutable classes better implement copyWithZone in the following way?

- (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;
    }
}

推荐答案

你最好的选择是在你的不可变超类中有一个 initWithMyImmutableObject 初始化器.然后你的子类可以使用

Your best option would be to have an initWithMyImmutableObject initialiser in your immutable superclass. Your subclass can then just implement NSCopying with

- (id) copyWithZone:(NSZone*)zone {
    return [[[self superclass] alloc] initWithMyImmutableObject:self]
}

这样,属性的实际复制是在超类的方法中完成的,该方法可以访问需要复制的所有私有成员.

That way the actual copying of properties is done in a method of your superclass, which has access to all private members that need to be copied.

这篇关于对于具有可变子类的不可变类,在 copyWithZone 中返回 [self retain] 真的安全/一个好主意吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆