views:

1907

answers:

4

I've read in several books... and online... about immutable and mutable strings. They claim "immutable strings" can't be changed. (But they never define "change".)

Which of these NSStrings could be changed without using NSMutableString?

The string contains "catfish"... and I later try to change it to "cat". (Same letters, just shorter.)

It contains "cat"... and I try to change it to "catfish". (Similar start... but just made longer.)

I change "cat" into "CAT". (Same letters, but just the case has changed.)

I change "cat" into "dog". (Totally different string, but the same length.)

I change "cat" into "dogwood". (Totally different string, but longer.)

+12  A: 

The answer is - none. Immutable means it cannot be changed into anything different than the original string. Every character stays the same, the length cannot change, etc. Once it's defined you cannot change anything about that string. If you want to make it longer or shorter or change any of the characters, you need to make a new string (or use a NSMutableString to begin with).

Marc Novakowski
Thanks for the quick reply. Doesn't that make NSString pretty useless? I set a *VARIABLE* to an NSString value... and then I can never change it. Isn't that commonly called a "constant" in other languages?I would (instead) probably want to "do something" with my stings 99% of the time. So shouldn't I be using MSMutableString almost everywhere? (But I rarely see it used, compaired to the VERY commonly used NSString.)
Donna
Imagine if int/float/long were also immutables.int x = 5;and then x can *NEVER* be changed.Immutable is (almost) useless. No?
Donna
"doing something" might simply imply reading them out from some data store and displaying them. In this case you won't want to modify them.
rein
There are many benefits to immutable classes. Check out the following article - it's Java-centric but the concepts apply to Objective-C as well: http://www.ibm.com/developerworks/java/library/j-jtp02183.html
Marc Novakowski
@BettyT: You are confusing the immutability of an object with the ability to assign to a variable which points to an object. An object is immutable if it has no methods that allow for its state to be changed. If you set a variable to point to an immutable object, you can still set the variable to point to any other object at any time. The object being immutable means that you know that once you point to an object, its state won't somehow change (e.g. by someone else who also has a variable that points to the same object). P.S. NSNumber objects are also immutable, but are not useless.
newacct
To expand on newacct's comment, it's VERY important to distinguish between variables and objects in Objective-C. Any number of variables can all point to the same object. Any of these variables can later be reassigned to a new object without affecting any of the others. On the other hand, if the object itself is mutated, every place in the code with a variable pointing to the object can see the changes to the object. Having an object change out from under you like that is often undesirable.
Chuck
A: 

You need to define "change", too :)

Basically, when you create an NSString, you're creating an array of characters and you're telling the compiler that the contents of said array will never change. The "never change" part is the "immutable" part; the data the string contains can't ever be modified.

On the other hand, an NSMutableString allows you to actually change the data it points to (hence it's 'mutable'). Note the 'appendString' method that exists for NSMutableString; this actually takes data and slaps it onto the end of the string.

For example, if you had:

NSString *myString = @"Cat"; myString = @"Goldfish";

That would work fine. You're never actually changing the data myString contains; you're simply telling it that you want it to point to a new segment of unchangeable data.

The only time you'd actually run into problems with the differences between mutable and immutable objects is if you tried to actually modify myString directly (e.g. append "s are cool" to it or something).

In other words, either class would allow you to "change" any string into any other string, but the methods you used to do it would be very different. For example, to turn "cat" into "CAT" with a mutable string, you could iterate over every character and simply make it uppercase (since you can modify the contents of a mutable string). With an immutable string, on the other hand, you'd have to first copy the original string elsewhere, modify it, and then redirect your variable to point to this new NSString.

The following links might be useful: http://www.kirupa.com/forum/showthread.php?t=307928 http://forums.macrumors.com/showthread.php?t=467099

I'd also recommend doing some googling; this is a question that relates to development in general, and it's a relatively important concept to grasp. It's also been discussed to death elsewhere on the internet.

Would it be "safer" and "more flexible" to just use NSMutableString everywhere? They say there's a "memory cost" and a "speed cost"... but... how much? 20 extra bytes from my pool of millions? Or slowing down my app by 0.01 seconds? (The benefits of "never have to worry about mutables" seems worth it.) Or is it?
Donna
If you're using concurrent programming (multiple threads, etc.) it's very nice to know that the contents of your string won't change in the middle of your use of it. If you had to worry about that, you'd probably make a copy of the string before doing anything else so that nobody will change it. Immutability makes it so that you don't have to copy the string. This becomes even more important for larger structures like NSArray and NSDictionary.If you've only got one thread (if you don't know what that means, you've only got one), then using mutables everywhere would probably be just fine.
BJ Homer
Even if you aren't using more than one thread, it's nice to know if an object can change out from under you. In general I find it simpler to use the immutable data structures most of the time. If I create an NSArray, give it to someone else and then continue to use it, it's helpful to know if someone may have changed it behind my back. In short, using mutable everywhere is easier to write, but much more difficult to debug.
rpetrich
Why would I write code where other parts of my code is changing my variables without my knowledge? Isn't that just Plain Poor Programming?
Donna
+5  A: 

If I declare a variable:

NSString * var;
// Here some code giving a new value to var

What is immutable is the object pointed to by var, not var itself.

This means that I cannot change anything of the object pointed to by var, but I can change which object is pointed to.

None of the operations you mention is allowed on var, but you can assign var with another different string:

NSString * anotherVar;
// Here some code giving a new value to anotherVar

var = anotherVar; // This is allowed (with a memory leak if GC is disabled)

// The following is also allowed: -stringWithFormat: creates a new object
var = [var stringWithFormat:@"%@ with more chars", var];
mouviciel
Just to note, that code should *not* result in a memory leak with GC disabled. What you're doing is a simple assignment, with no -retain or -copy involved. Thus, no memory leak.Also, your string format should be @"%@ with more chars", since %s only applies for C-Strings, I believe.
Matt Ball
Thanks, I have updated the format. About the memory leak, it depends on how the first value of var has been created.
mouviciel
+1  A: 

An immutable string (or indeed, any immutable object) is one that can't be changed at all after initialisation.

Here's the advantage of using immutable strings, in (pseudo-)pseudo-code:

// if using mutable strings
let a = "Hello World";
let b = a;
a.replace("Hello", "Goodbye");

Now what does a hold? "Hello World"? "Goodbye World"? Now what does b hold?

If strings are mutable, then it might hold "Goodbye World". This may be what you want. It might not be.

With immutability, it becomes very clear that b still points to the original string, because the replace method can't have changed the actual string, but rather returned a reference to a new string.

You might not see much benefit in this example. But if a and b are referenced and used in different parts of the code, or in different threads, having immutable references removes a lot of potential errors.

Steve McLeod