使用NSCopying复制私有实例变量的最佳实践

10

我可能在这里遗漏了一些明显的东西,但我正在实现一个对象的 NSCopying。该对象有私有实例变量,不通过 getter 方法暴露,因为它们不应该在对象外部使用。

在我的 copyWithZone: 实现中,我需要 alloc/init 新实例,并设置其状态以匹配当前实例。显然,我可以从 copyWithZone: 中访问当前私有状态,但我无法将其设置到新对象中,因为没有访问器可用于该状态。

是否有标准方法解决这个问题,同时保持数据隐私不受影响?

谢谢。

3个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
8

首先,即使是私有的,你也应该始终拥有getter。除非在极少数情况下,你的对象只能使用访问器来访问自己的实例变量。这将避免你在内存管理方面遭受很大的痛苦。

其次,Alex提出使用->的建议是标准方法,即使这违反了上述getter规则。其中有一些例外情况,而copy就是其中之一。在这里使用私有setter仍然是合理的(我过去一直这样做),但出于各种原因,使用->通常更加简洁。

非常小心地正确处理内存管理。如果你需要调用[super copyWithZone:],那么你也应该阅读有关NSCopyObject()的复杂性以及它对你的影响,即使你自己不使用它。我在“NSCopyObject() considered harmful.”中详细讨论了这个问题。


感谢提到私有访问器以及 NSCopyObject 的危险。 - Ben Zotto
我不确定只读访问器如何帮助内存管理?如果您没有与assignretain一起使用它,那么使用getter还是直接使用变量都没有区别。 - Hemant
@Hemant,因为调用者不应该关心属性当前(或将来)是否只读。这不是调用者的业务,它可能随着时间的推移而改变,然后您需要查找每个错误的代码片段。遵循简单的规则,错误变得明显。当您说“哦,除非我知道它目前没问题”时,您会为自己带来维护方面的麻烦。 - Rob Napier

5

您可以直接访问副本的实例变量。您可以使用与结构体相同的指针解引用语法。因此,例如,如果您的类是这样的:

@interface MyCopyableClass : NSObject {
    int anInstanceVariable;
}
@end
你可以这样做:
- (id)copyWithZone:(NSZone *)zone {
    MyCopyableClass *theCopy = [[[self class] allocWithZone:zone] init];
    theCopy->anInstanceVariable = anInstanceVariable;
    return theCopy;
}

1
一种选择是创建一个自定义的初始化器,接受私有 iVar 的值。因此,您可以像这样创建它:
-(id) initWithPropertyOne:(SomeClass *) anObject andPropertyTwo:(SomeClass *) anotherObject;
当你实例化副本时,只需使用自定义初始化程序。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,