Re: Determining whether a dictionary is mutable or not
Re: Determining whether a dictionary is mutable or not
- Subject: Re: Determining whether a dictionary is mutable or not
- From: Jean-Daniel Dupas <email@hidden>
- Date: Sat, 15 Jan 2011 17:47:29 +0100
Le 15 janv. 2011 à 13:18, Tito Ciuro a écrit :
> On Jan 15, 2011, at 1:04 PM, Ken Thomases wrote:
>
>> On Jan 15, 2011, at 5:38 AM, Tito Ciuro wrote:
>>
>>> On Jan 15, 2011, at 7:36 AM, Ken Ferry wrote:
>>>
>>>> I'm not sure this has been made clear: It is intentional that it is difficult to determine whether a dictionary is mutable.
>>>>
>>>> That's because you shouldn't do it. Whether a dictionary is mutable _to_you_ is a matter of what's in the header for the method you obtained it from.
>>>>
>>>> Suppose that some object keeps a mutable array as its internal state. It also has an accessor that lets you look at the array as an immutable array. If you introspect it and realize its mutable, is it safe to mutate? No! It's part of the object's internal state, you cannot just mess with it.
>>>>
>>>> It is unsafe in general to introspect mutability.
>>>>
>>>> -Ken
>>>> Cocoa Frameworks
>>>
>>> It makes sense what you're saying because introspecting an object bypassing its accessors would break encapsulation. From the client's perspective this is very clear: use the methods provided and don't mess with the internals. Roger that.
>>>
>>> However, how about the other way around? Say you have the same class you mentioned. Internally, it has a mutable array which one can manipulate via dedicated accessors. This object has an init method which accepts an array as input. The client is (should?) be free to pass an immutable or mutable array with values. I see at least two ways to honor this input and initialize the object:
>>>
>>> 1) add the input objects to the internal array (i.e. - (void)addObjectsFromArray:(NSArray *)otherArray)
>>> 2) assign the mutable version of the input array to the internal array (i.e. internalArray = [theInputArray mutableCopy])
>>>
>>> In case of #2, (perhaps mistakenly) I was attempting to check whether it was necessary to mutate an already mutable array. It just seemed like the right thing to do: figure out whether the input array is mutable, if it isn't then make it mutable. Then proceed to set the array as the object's contents. However, since this init process is called once, perhaps it just makes sense to always call mutableCopy and be done regardless of the input type. Would this be the right approach perhaps?
>>>
>>> My main concern is how to deal with this mutability/non-mutability from the inside, not the outside.
>>
>> You should copy any state which you need to be private.
>>
>> What if the code which calls your init method had, in fact, passed a mutable array? Why in the world would you want to make that your internal state? That would mean that your internal state is open to manipulation from the outside. The caller could, after the new object is initialized, modify its (the caller's) mutable array. They have thus unwittingly modified the internal state of the new object.
>>
>> And, again, if you had declared your initializer to take an immutable object as its parameter, why would you imagine that the caller would be OK with you mutating it?
>>
>> Sharing state is always fraught with difficulties. When it comes to value objects, including collections, you should default to making copies. Only retain them (and thus share state with the provider) after careful consideration of the close coupling that would result. And even then, it makes little sense to have the behavior be conditional on the object's mutability.
>>
>> I'll also point out that code which tries to determine the mutability and then takes one of two different paths is more complex and error-prone than code which just does one straightforward thing.
>>
>> Regards,
>> Ken
>
> Ken, looks like I wasn't clear enough. In general (not only in this case) I would not retain the array unless it was immutable. Otherwise, as you well point out, retaining a mutable one would allow external clients manipulate the array bypassing the accessors provided, thus breaking encapsulation.
And as a side note. When you need an immutable copy, don't bother to try to optimize by copying if mutable and retaining if immutable, this is already what the copy implementation does.
If properly implemented (and that is the case for the Cocoa framework), [myImmutableObject copy] should simply returns [self retain];
> I understand that my original approach was flawed because I really don't need (nor should I care) about the original state of the collection being passed: since the class allows the data to be manipulated via accessors, the inited data, if provided, should be copied internally regardless of the array state being passed. That would make a private copy of the data only accessible via the class accessors.
>
> I was looking for a solution where there was not a problem.
>
> Best regards,
-- Jean-Daniel
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden