What is the logic behind having a mutable and immutable versions of classes like NSArray, NSDictionary etc in Objective C?
Why do common collection classes in Objective C like NSString, NSArray, NSDictionary etc have a mutable as well as 开发者_如何学Can immutable version. What is the logic behind defining them separately? Performance, memory management or anything else?
The immutable versions of the classes exist because an immutable object is, in and of itself, a unique identifier for a particular state. I.e. if you have an NSArray
of 100 NSString
instances, that NSArray
instance can be treated as idempotent for any one of those strings.
As well, the immutability means that a change cannot happen after the state has been vended. For example, NSView
's subviews
method returns an immutable array, thus ensuring that the caller isn't going to play games with the contents (nor even expect to be able to). Internally, NSView
could choose to return the [likely] NSMutableArray that contains the subviews (since it is internally mutable) and the typecast to NSArray
means the caller can't manipulate the contents without an evil cast or bad compiler warning. (This may or may not actually be the real implementation, btw -- but this pattern is used elsewhere).
Immutability also means that enumeration and/or traversal can be done without risk of a state change in the middle. Similarly, many immutable classes are also explicitly thread safe; any number of threads can simultaneously read the immutable state, often without need for a lock.
In general for an API, an immutable class is going to be thread safe so you can read it directly in a background thread without worrying the contents will change...
That matters more for things like a collection where contents can shift and you might be in the middle of enumerating them.
Why do common collection classes in Objective C like NSString, NSArray, NSDictionary etc have a mutable as well as an immutable version.
the concept is used in related langauges. the notable distinction is that the objc types are named mutable variants. similar langauges typically accomplish this via application of a keyword, such as const
. of course, other related languages also use types which are explicitly mutable or immutable.
What is the logic behind defining them separately?
objc messaging does not distinguish const and non-const, and the language does not provide builtin support for ensuring an object's state does not change (although it really would not be a difficult addition if one were really inclined to extend a compiler). so there's a little bit of history involved here too.
therefore, it's convention for the class to define immutability vs mutability, and to supply variants which distinguish mutability.
multiple abstractions also introduce type safety and intention.
Performance
yes. there are multiple optimizations an invariant object can make.
some cases include:
- it could cache values, never computing them more than once.
- it could use exact, nonresizable allocations for its data.
- it often does not need any special code for multithreaded use -- many immutable types will only mutate during construction/destruction.
- these types often use class clusters. if a class cluster is implemented, then specialized implementations can provide significant differences in memory, implementation, etc. consider how an immutable string with exactly one character could differ from a mutable variant.
memory management
some cases include:
- immutable types could share their immutable contents.
- they may also reduce allocations. for example, an implementation of
copyWithZone:
orinitWithType:
could return the source retained, rather than a deeep or shallow physical copy.
or anything else?
it makes it easier to write clear interfaces. you can guarantee and (attempt to) restrict some things. if everything were mutable, there would be many more mistakes to make and special cases. in fact, the distinction could entirely change the way we approach writing objc libraries:
[[textField stringValue] appendString:@" Hz"];
[textField stateDidChange];
so it's nice to be able to pass objects around without worrying that the client will change behind your back, while avoiding copying all over the place.
Basically, when you know that a data structure is immutable, you can make many optimizations around that. For example, if an array is immutable, you can leave out all the code that would "grow" the array whenever you attempted to add an object, and you can simply have your immutable array be a wrapper around an id[]
.
Apart from the answers mentioned above one difference is : Immutable objects are generally thread safe. Whereas, a Mutable objects are not thread safe.
thanks
精彩评论