了解副本和可变副本

understanding copy and mutable copy

提问人:Pinxaton 提问时间:4/19/2014 最后编辑:Pinxaton 更新时间:4/19/2014 访问量:248

问:

请考虑以下几点:

// BaseClass is both NSCopyable and NSMutableCopyable
@interface MyClass : BaseClass {
    // a bunch of properties
}

// x is a MyClass* local variable in a method
MyClass *a = [x copy];         // a is a strong reference to an immutable copy?
MyClass *b = [x mutableCopy];  // b is a strong reference to a mutable copy?

问题:

  1. 我可以对 a 的 iVar 进行任何更改吗?如果没有,如果我尝试对任何 iVar 进行更改,会发生什么情况?我是否会遇到不确定的行为,例如,有时它有效,有时它不起作用,内存损坏,或者编译器是否完全禁止它?

  2. 我可以对 b 的 iVar 进行任何更改吗?

目标-C 复制 语义学 可变

评论


答:

1赞 tia 4/19/2014 #1

简答题

  1. 是的。没有内存损坏,如果 iVar 可访问,则不会出现编译错误。
  2. 与 1 相同。

长答案

可变和不可变副本是 Apple 基础类中的核心概念之一,例如 或 。如 NSCopying 协议中所述,实现“不可变与可变”概念的类必须返回 copyWithZone: 的不可变对象NSStringNSArray

但是,编译器或内存保护不会强制执行对象的不可变性,但类设计者必须设计类以使其在接收消息时返回不可变对象。copy

在你的例子中,实现这种东西的常用方法是使不可变,并使其子类化并使其可变。您的呼叫站点应如下所示:MyClassMyMutableClass

MyClass *a = [x copy];         
MyMutableClass *b = [x mutableCopy]; 

请注意,实现可变/不可变有时非常乏味,因此请确保您有足够的理由来实现此类功能。

评论

0赞 Pinxaton 4/19/2014
现在假设我正在从 SpriteKit 库中复制一个类似 SKNode 的类,该库实现了 NSCopying,但不实现 NSMutableCopying。当我在 SKNode* 上调用 copy 而不是 mutableCopy 时,鉴于它不实现 NSMutableCopying,我是否假设它返回的对象是可变的?从您上面的解释中我的理解是,除非存在类的可变版本,例如 SKMutableNode,否则我可以假设我可以修改返回的副本?
0赞 tia 4/20/2014
在常见情况下,您可以假设这一点。然而,这实际上取决于实现,因为合约没有说明这种情况的任何内容,例如它可能是深克隆或浅克隆,或者任何东西。我建议,如果文档(例如 SpriteKit 文档)没有阐明方法的性质,那么常识在这里非常有用。NSCopyingcopy