-copy 什么时候返回可变对象?
我在 Cocoa 和 Objective C:启动并运行中读到 -copy
将始终返回不可变对象,而 -mutableCopy
将始终返回可变对象:
重要的是要知道在可变对象上调用
-copy
会返回不可变对象 版本。如果你想复制一个可变对象并在新版本中保持可变性, 您必须在原始文件上调用-mutableCopy
。不过,这很有用,因为如果你想要 要“冻结”一个可变对象,您只需对其调用-copy
即可。
所以我有这样的事情:
NSMutableURLRequest *req = [[NSMutableURLRequest alloc] init];
NSLog( @"%@", [req className] ); // NSMutableURLRequest
NSLog( @"%@", [[req copy] className] ); // NSMutableURLRequest
NSLog( @"%@", [[req mutableCopy] className] ); // NSMutableURLRequest
根据这个 以前的答案:
你不能依赖复制的结果是可变的!复制
NSMutableArray
可能 返回一个 NSMutableArray ,因为那是原始类,但复制任意NSArray
实例不会。
这似乎与 NSURLRequest
有点隔离,因为 NSArray
按预期行事:
NSArray *arr = [[NSMutableArray alloc] init];
NSLog( @"%@", [arr className] ); // __NSArrayM
NSLog( @"%@", [[arr copy] className] ); // __NSAraryI
NSLog( @"%@", [[array mutableCopy] className] ); // __NSArrayM
所以...
- When does
-copy
return an immutable object (as预期)以及何时返回可变对象? - 如何达到获得拒绝“冻结”的可变对象的“冻结”副本的预期效果?
I read in Cocoa and Objective C: Up and Running that -copy
will always return an immutable object and -mutableCopy
will always return a mutable object:
It’s important to know that calling
-copy
on a mutable object returns an immutable
version. If you want to copy a mutable object and maintain mutability in the new version,
you must call-mutableCopy
on the original. This is useful, though, because if you want
to “freeze” a mutable object, you can just call-copy
on it.
So I have something like this:
NSMutableURLRequest *req = [[NSMutableURLRequest alloc] init];
NSLog( @"%@", [req className] ); // NSMutableURLRequest
NSLog( @"%@", [[req copy] className] ); // NSMutableURLRequest
NSLog( @"%@", [[req mutableCopy] className] ); // NSMutableURLRequest
According to this previous answer:
You cannot depend on the result of copy to be mutable! Copying an
NSMutableArray
may
return anNSMutableArray
, since that's the original class, but copying any arbitraryNSArray
instance would not.
This seems to be somewhat isolated to NSURLRequest
, since NSArray
acts as intended:
NSArray *arr = [[NSMutableArray alloc] init];
NSLog( @"%@", [arr className] ); // __NSArrayM
NSLog( @"%@", [[arr copy] className] ); // __NSAraryI
NSLog( @"%@", [[array mutableCopy] className] ); // __NSArrayM
So...
- When does
-copy
return an immutable object (as expected) and when does it return a mutable object? - How do I achieve the intended effect of getting a "frozen" copy of a mutable object that refuses to be "frozen"?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
将对象转变为可变对象的最佳方法是使用可变“构造函数”。例如:
Copy 用于制作对象的副本。不改变它的可变性。
The best way to turn an object into an mutable one is to use the mutable 'constructor'. Like for example:
Copy is used to make a copy of an object. Not to change it's mutability.
我认为你已经发现了文档和现实之间的巨大裂痕。
NSCopying 协议文档声称:
但在某些情况下,这显然是错误的,正如您在示例中所示的那样(并且我已通过该文档页面向他们发送了有关此问题的反馈)。
但是(#2)在我看来,这实际上并不重要,你不应该关心。
-copy
的要点是它将返回一个您可以使用的对象并保证其行为独立于原始对象。这意味着如果您有一个可变对象,请复制
它,并更改原始物体,复制后看不到效果。 (在某些情况下,我认为这意味着-copy
可以优化为不执行任何操作,因为如果对象是不可变的,那么它首先就无法更改。我对此可能是错的。 (我现在想知道因此对字典键有什么影响,但这是一个单独的主题...))正如您所见,在某些情况下,新对象实际上可能是一个可变类(即使文档告诉我们它不会)。但只要您不依赖它的可变性(为什么要这样做?),那就没关系。
你应该做什么? 始终将
-copy
的结果视为不可变,就这么简单。I think you've uncovered a great rift between documentation and reality.
The NSCopying protocol documentation claims:
But this is clearly wrong in some cases, as you've shown in your examples (and I've sent feedback to them about this via that documentation page).
But(#2) in my opinion, it doesn't actually matter and you shouldn't care.
The point of
-copy
is that it will return an object you can use with the guarantee that it will behave independently of the original. This means if you have a mutable object,-copy
it, and change the original object, the copy will not see the effect. (In some cases, I think this means that-copy
can be optimized to do nothing, because if the object is immutable it can't be changed in the first place. I may be wrong about this. (I'm now wondering what the implications are for dictionary keys because of this, but that's a separate topic...))As you've seen, in some cases the new object may actually be of a mutable class (even if the documentation tells us it won't). But as long as you don't rely on it being mutable (why would you?), it doesn't matter.
What should you do? Always treat the result of
-copy
as immutable, simple as that.您应该始终将其视为不可变的变体。不应使用返回类型的可变接口。除了优化之外,答案应该不重要,并且应该被视为实现细节,除非有记录。
明显的例子:由于多种原因,objc 类集群和类设计可能很复杂。返回可变副本可能只是为了方便。
使用不可变类的复制构造函数是一个好方法(类似于St3fan的答案)。就像
copy
一样,它不是一个保证。我能想到的为什么你想要强制执行这种行为的唯一原因是为了性能或强制执行受限的接口(除非它是学术性的)。如果您想要性能或受限接口,那么您可以简单地封装该类型的实例,该实例在创建时复制并仅公开不可变接口。然后你通过保留来实现复制(如果这是你的意图)。
或者,您可以编写自己的子类并实现自己的副本变体。
最后的手段:许多可可可变/不可变类都是纯粹的接口 - 如果您需要确保特定的行为,您可以编写自己的子类 - 但这是很不寻常的。
也许更好地描述为什么应该强制执行这一点会很好 - 现有的实现对于绝大多数开发人员/用户来说工作得很好。
you should always treat it as the immutable variant. the mutable interface of the returned type should not be used. apart from optimizations, the answer should not matter and should be considered an implementation detail unless documented.
the obvious case: for a number of reasons, objc class clusters and class designs can be complex. returning a mutable copy could simply be for convenience.
using the copy constructor of the immutable class is a good way (similar to St3fan's answer). like
copy
, it's not a guarantee.the only reason i can think of as to why you would want to enforce this behaviour is for performance or to enforce a restricted interface (unless it's academic). if you want performance or a restricted interface, then you can simply encapsulate an instance of the type which copies on creation and exposes only the immutable interface. then you implement copy via retain (if that's your intent).
alternatively, you can write your own subclass and implement your own variant of copy.
final resort: many of the cocoa mutable/immutable classes are purely interface - you could write your own subclass if you need to ensure a particular behaviour -- but that's quite unusual.
perhaps a better description of why this should be enforced would be good - the existing implementations work just fine for the vast majority of developers/uses.
请记住,不存在单一的
复制
实现——每个类都实现自己的。而且,众所周知,Objective C 运行时的实现有些地方有点“松散”。所以我认为我们可以说大部分copy
返回一个不可变的版本,但也存在一些例外。(顺便说一句,这是做什么的:
?)
Bear in mind that there is not one
copy
implementation -- each class implements its own. And, as we all know, the implementation of the Objective C runtime is a little "loosey goosey" in spots. So I think we can say that mostlycopy
returns an immutable version, but some exceptions exist.(BTW, what does this do:
?)