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. 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, -- Tito _______________________________________________ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) 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: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com