Mutability refers to the ability to mutate or change. Immutable refers to lacking the ability to mutate or change. These are my notes from the apple developer website. I rewrite my notes because it helps me to retain the information I am learning and use most often with my line of work as a mobile developer.
Objective-C Cocoa objects can be either mutable or immutable. Immutable objects contain encapsulated objects that can not be changed after they are created. The encapsulated objects inside immutable objects have values that will remain the same for the life of the object. If an encapsulated object is inside a mutable object, the value can be changed at any time.
Cocoa objects are mutable by default and most will let us change their encapsulated data when we use setter and getter methods. I setup my setters and getters by synthesizing my property declarations (model objects) from my .h file in my .m file. Model objects require setter methods before we can change the instance data.
The Foundation framework introduces mutable and immutable classes. The mutable subclasses are usually subclasses of their immutable superclass and they are easy to recognize because they use the word “Mutable” in their class name. Examples: NSMutableArray, NSMutableData. The Foundation framework defines all mutable classes. The AppKit framework includes NSMutableParagraphStyle and any Cocoa framework might have it’s own mutable and immutable classes.
Immutable objects can be ones that encapsulate collections of discrete values or contain values that will be stored in buffers. Immutable objects’ values are stable in theory but not guaranteed. If serializing a property list with NSPropertyListSerialization, the mutability is not preserved because only the general object mutablity is preserved (dictionary, array..). So when we deserialize the property list, the resulting objects may not be the same class as the original objects. Maybe the NSMutableDictionary object is now a NSDictionary object.
NSNumber or NSDate can be mutable objects because they contain a single simple value. Mutable objects might be less efficient than their immutable counterpart because they must dynamically manage a backing store that is able to change.
Using Mutable Objects
- Use mutable variant of an object when we need to change its contents frequently and incrementally after it’s been created.
- Look at return type for indications of mutability.
- Go with immutable if you have any doubts about if an object is or should be mutable.
- Most instance vars holding string values should be assigned immutable NSString objects that are replaced with setter methods. Sometimes it’s preferable to replace one immutable object with another.
Create and Convert Mutable Objects
Use standard nested alloc-init.
NSMutableDictionary *mutDict = [[NSMutableDictionary alloc] init];
Use initializers and factory methods.
NSMutableArray *mutArray = [NSMutableArray arrayWithCapacity:[timeZones count]];
Make a mutable copy of an existing object by invoking mutableCopy method that each immutable super class of a Foundation mutable class uses. Or you can send copy to a mutable object to make an immutable copy of the object.
NSMutableSet *mutSet = [aSet mutableCopy];
Storing & Returning Mutable Instance Vars
Use immutable when an object has contents that will change alot. Strings and data objects are usually immutable. Use mutable when an object changes incrementally. Collections, arrays, and dictionaries are usually mutable. Frequency of changes and size of collection should also be considered when deciding to make an object mutable or immutable. A small array that rarely changes should be immutable.
Use immutable if we are at risk of mutating something the end user might have reference to, such as a collection that frequently changes and is returned to user via a getter accessor method.
If the value of the instance var changes frequently but we rarely return it to clients in getter methods; make the instance var mutable but return an immutable copy of it in the accessor method.
Maintain a flag that records if the object is currently mutable or immutable. If there is a change, make the object mutable and apply the change. When handing out the collection, make the object immutable before returning it, if needed.
Receiving Mutable Objects
The method invoker wants to know if the object’s value can be changed and if the value will change unexpectedly while it has a reference to it. Don’t use introspection, use return type instead. Do not assume an object is mutable based on its class membership. Base my decision solely on what the signature of the method vending the object says about it’s mutability. If I’m not sure, assume it’s immutable.
Make Snapshots of Received Objects
If I want to make sure an immutable object received from a method will not mutate without me knowing about it, make a snapshot of the object by copying it locally and occasionally comparing to the stored version of the object with the most recent version. If you see the object mutated, adjust your code where it is dependent on the previous version of the object. Making snapshots can be an expensive problem because we are making multiple copies of the same object. Use key-value observing for an efficient alternative.
Mutable Objects in Collections
Problems can happen from storing mutable objects in collection objects. Some collections turn invalid or corrupt if the objects they hold mutate because the objects affect the way they are placed in the collection. The object properties that are keys in hashing collections (NSDictionary or NSSet) will corrupt the collection if they affect the object’s hash or isEqual methods when they change. If an object in an ordered collection (sorted array) changes its properties, it will affect how the object compares to other objects in the array, rendering the ordering invalid.
References:
Object Mutability. Concepts in Objective-C Programming. Mac Developer Library. Retrieved November 29th 2012 from http://developer.apple.com/library/mac/#documentation/General/Conceptual/CocoaEncyclopedia/ObjectMutability/ObjectMutability.html
