首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >-copy什么时候返回可变对象?

-copy什么时候返回可变对象?
EN

Stack Overflow用户
提问于 2011-08-27 02:56:06
回答 4查看 2K关注 0票数 9

我在中看到,-copy总是返回一个不可变的对象,-mutableCopy总是返回一个可变的对象:

重要的是要知道,对可变对象调用-copy会返回不可变的版本。如果要复制可变对象并在新版本中保持可更改性,则必须在原始版本上调用-mutableCopy。但是,这是有用的,因为如果您想“冻结”一个可变对象,只需在它上调用-copy即可。

所以我有这样的东西:

代码语言:javascript
复制
NSMutableURLRequest *req = [[NSMutableURLRequest alloc] init];
NSLog( @"%@", [req className] );               // NSMutableURLRequest
NSLog( @"%@", [[req copy] className] );        // NSMutableURLRequest
NSLog( @"%@", [[req mutableCopy] className] ); // NSMutableURLRequest

根据这个previous answer

,您不能依赖复制的结果是可变的!复制NSMutableArray可能会返回一个NSMutableArray,因为这是原始类,但是复制任何任意NSArray实例都不会。

这似乎在某种程度上孤立于NSURLRequest,因为NSArray的作用与预期的一样:

代码语言:javascript
复制
NSArray *arr = [[NSMutableArray alloc] init];
NSLog( @"%@", [arr className] );                 // __NSArrayM
NSLog( @"%@", [[arr copy] className] );          // __NSAraryI
NSLog( @"%@", [[array mutableCopy] className] ); // __NSArrayM

所以..。

  1. -copy何时返回不可变对象(如预期的那样),以及何时返回可变对象?
  2. 如何获得拒绝“冻结”的可变对象的“冻结”副本的预期效果?
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-08-27 04:00:57

我认为你已经发现了文档和现实之间的巨大裂痕。

NSCopying协议文档声称:

如果考虑“不可变的还是可变的”适用于接收对象,则返回的副本是不可变的;否则,副本的确切性质由类决定。

但在某些情况下,这显然是错误的,正如您在示例中所展示的那样(我已经通过文档页面向他们发送了有关这方面的反馈)。

但是(第二)在我看来,其实并不重要,你也不应该在意。

-copy的要点是,它将返回一个可以使用的对象,保证它将独立于原始对象运行。这意味着,如果您有一个可变对象,-copy它,并更改原始对象,副本将不会看到效果。(在某些情况下,我认为这意味着-copy可以被优化为什么都不做,因为如果对象是不可变的,那么它一开始就不能更改。我可能弄错了。(我现在想知道这对字典键意味着什么,但这是一个单独的主题.)

正如您已经看到的,在某些情况下,新对象实际上可能是一个可变的类(即使文档告诉我们它不会)。但是,只要你不依赖于它是可变的(你为什么要这么做?),这并不重要。

你应该怎么做呢?总是把的结果当作不变的,就这样简单。

票数 13
EN

Stack Overflow用户

发布于 2011-08-27 04:18:43

1) -copy何时返回不可变对象(如预期的那样)以及何时返回可变对象?

你应该始终把它看作是不变的变体。不应使用返回类型的可变接口。除了优化,答案不应该重要,应该被视为一个实现细节,除非有文档记录。

显而易见的情况是:由于许多原因,objc类集群和类设计可能很复杂。返回可变副本可能只是为了方便。

2)如何获得拒绝“冻结”的可变对象的“冻结”副本的预期效果?

使用不可变类的复制构造函数是一种很好的方法(类似于St3fan的答案)。就像copy一样,这不是一个保证。

我能想到的唯一原因是,您希望执行此行为是为了性能或强制执行受限的接口(除非它是学术性的)。如果您想要性能或受限制的接口,那么您可以简单地封装一个类型的实例,该实例在创建时复制,并且只公开不可变的接口。然后通过retain实现复制(如果这是您的意图)。

或者,您可以编写自己的子类并实现自己的副本变体。

最后的解决办法:许多可可变/不变类纯粹是接口--如果需要确保特定行为,您可以编写自己的子类--但这是非常不寻常的。

也许更好地描述为什么要强制执行这一点是很好的--现有的实现对绝大多数开发人员/使用来说都很好。

票数 3
EN

Stack Overflow用户

发布于 2011-08-27 03:03:37

请记住,没有一个copy实现--每个类都实现自己的。而且,众所周知,在spots中,目标C运行时的实现有点“松懈”。因此,我认为我们可以说,大多数情况下,copy返回一个不可变的版本,但也存在一些例外。

(顺便说一句,这是做什么的:

代码语言:javascript
复制
NSArray *arr = [[NSMutable array] init];

?)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7212268

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档