What is the logic behind having a mutable and immutable versions of classes like NSArray, NSDictionary etc in Objective C?
Asked Answered
H

5

20

Why do common collection classes in Objective C like NSString, NSArray, NSDictionary etc have a mutable as well as an immutable version. What is the logic behind defining them separately? Performance, memory management or anything else?

Hypotaxis answered 4/7, 2011 at 1:54 Comment(0)
S
14

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.

Sewerage answered 4/7, 2011 at 3:9 Comment(0)
P
12

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.

Pastoralize answered 4/7, 2011 at 1:58 Comment(5)
Just because an object is immutable, it does not mean that operations on the object are threadsafe. That happens to be the case with some of the most basic objects in Foundation, like NSString, but that's due to implementation, not contract.Pigweed
Theoretically true, but generally the only reason someone would split out mutable and immutable versions of a class is because they wanted thread safety - otherwise why not stick with the simplicity of just having the mutable version? Can you think of any examples where immutable classes have been made for widespread use without being thread safe?Pastoralize
Actually, the thread safety of the immutable NS collections and immutable NSStrings is documented (but, yes, immutability, in general, does not mean thread safe). There are plenty of examples of immutable objects that are not thread safe due to internal implementation details (such as cache filling).Sewerage
I realized my original wording was too strong - I agree that immutability is not a guarantee of thread safety as I stated in my off the cuff reply. So I edited it with some qualifications. But I still feel like I have never run across an API where when something that had immutable/mutable variants, did not have the immutable variant thread safe. Sure there's lots of code people have written where something that happens to be immutable is not thread safe, but that is different than something split into immutable/mutable where a lot of thought is going into the division and the reasons why.Pastoralize
Another good feature of immutable objects is that you can share them promiscuously; since they don't change (well, not at the contract level), they won't surprise anyone. Mutable objects have to have their own identity and you've got to be much more careful with them.Ursulina
L
10

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: or initWithType: 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.

Ludeman answered 4/7, 2011 at 4:39 Comment(0)
N
8

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[].

Nicety answered 4/7, 2011 at 1:59 Comment(1)
Essentially, immutable classes can have a sort of efficiency bonus over similar mutable classes.Ondrea
M
-1

Apart from the answers mentioned above one difference is : Immutable objects are generally thread safe. Whereas, a Mutable objects are not thread safe.

thanks

Magdalenemagdalenian answered 17/4, 2017 at 17:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.