13

I'm new to object-oriented programming, and one concept that has been taking me a while to grasp is immutability. I think the light bulb went off last night but I want to verify:

When I come across statements that an immutable object cannot be changed, I'm puzzled because I can, for instance, do the following:

NSString *myName = @"Bob";
myName = @"Mike";

There, I just changed myName, of immutable type NSString. My problem is that the word, "object" can refer to the physical object in memory, or the abstraction, "myName." The former definition applies to the concept of immutability.

As for the variable, a more clear (to me) definition of immutability is that the value of an immutable object can only be changed by also changing its location in memory, i.e. its reference (also known as its pointer).

Is this correct, or am I still lost in the woods?

Michael Mangold
  • 365
  • 1
  • 2
  • 11
  • 13
    Your your type is not an `NSString`, it is a "_pointer to_ and `NSString`", which is not immutable. I know nothing of objective C, but I'm guessing in your example that `@"Mike"` is creating a new instance of `NSString` and assigning it to the _pointer_, `myName`. So you haven't changed the object that `myName` was pointing to, just what it was pointing to. –  Jun 29 '11 at 12:44
  • 2
    @fwgx Put it as an answer and you'll get my upvote. – Gulshan Jun 29 '11 at 13:02
  • Thank you everyone for all the replies, they are very helpful. I now uderstand that the immutable object is the value in memory, not the variable which points to it. – Michael Mangold Jun 29 '11 at 15:57
  • @Gulshan Done, see below.... –  Jun 29 '11 at 19:56
  • To understand immutability, I recommend learning a programming language that clearly separates binding (i.e. giving names to objects) with mutability (i.e. allowing a name to be reassigned to a different object). ML (in any guise: SML, Ocaml, F#) is a good example. – Gilles 'SO- stop being evil' Jun 30 '11 at 23:23

7 Answers7

18

You are lost at words. Immutability means: As long as you don't change the variable, it will always "contain" the same value, not matter what you do with other variables.

Counterexample in C (a bit simplified, assuming an architecture that allows that):

 char *a = "Hello World";
 char *b = a;
 b[0] = 'Y';

Now a no longer "contains" (i.e. points at) the string "Hello World", but it's "Yello World" instead.

In languages where strings are immutable, like Java and (EDIT: safe) C#, you cannot do that. No way. This means that every part of the program can safely keep a reference to the string and rely that its contents never change; otherwise, they would have to create a copy just to be on the safe side.

But the variable still is mutable. You can let it point to another object. It's just that the object itself won't change behind your back.

user281377
  • 28,352
  • 5
  • 75
  • 130
  • 1
    You technically *can* modify string contents in C#, you just have to use `unsafe` code. – Aaronaught Jun 29 '11 at 16:57
  • 1
    Aaronaught: Thanks for the info, you are right; for everyone who needs to know how: http://msdn.microsoft.com/en-us/library/ms228599.aspx – user281377 Jun 29 '11 at 18:35
11

You are confusing variables with objects. Variables can be used to store references to objects, but they are NOT objects. It is objects that are immutable, not variables, so you can change the variable from one object to another, but you cannot change the attributes of the object if its immutable.

Think of the object as a loud, drunken neighbour. If he is reasonable (mutable), you might be able to knock on his door and convert him to a lifestyle where he doesn't make as much noise. But if he is immutable, your only change is to hope that someone else moves in!

Kilian Foth
  • 107,706
  • 45
  • 295
  • 310
6

A variable is not an object. A variable is a name, that refers to an object (or more generally a value).

For example "the goalkeeper" is a name we use to refer to the object (person) responsible to defend the goal. But if I substitute that person by another (because the former is injured or whatnot), the new person is now referred to as the "goalkeeper".

The assignment statement is what makes variables mutable (some languages, such as Haskell don't have it and in fact use immutable variables). It allows you to redefine the meaning of a name and thereby reassign the value.

Now objects themselves can be immutable. A few thousand years ago one could have thought of diamonds as being immutable. No matter what you did with a diamond, you could not modify it. Whether you called it waggawooga (loosely translates to "our tribe's biggest shiny stone") or ceased to call it that way (because you found a bigger one), the diamond stayed the same. In contrast the piece of wood you used to carve in funny pictures with your waggawooga did not stay the same. It proved mutable. Even if it had the same name all the time.

Both variables and values can be immutable (independently). In this case, it's the objects which are immutable. Once you construct an NSString, you can not modify it. You can call it names and pass it around, but it'll stay the same. In contrast to that, NSMutableString can be changed after creation, for example by calling the setString method.

Michael K
  • 15,539
  • 9
  • 61
  • 93
back2dos
  • 29,980
  • 3
  • 73
  • 114
  • Love the waggawooga comparison! – Michael K Jun 29 '11 at 13:55
  • Just so as to not confuse the original poster more than necessary: though your point that a variable is not an object is good, a variable is not actually defined as "a name that refers to a value". A variable is *possibly* named, and refers to a *storage location* that contains a value. In many programming languages variables need not be named, and in many languages the same variable can have more than one name. – Eric Lippert Jun 29 '11 at 17:04
5

It sounds like you're heading in the right direction, but haven't quite got it yet. This is wrong:

There, I just changed myName, of immutable type NSString. My problem is that the word, "object" can refer to the physical object in memory, or the abstraction, "myName."

In your code snippet, myName is not of immutable type NSString, it is of mutable type NSString* (pointer to NSString). It sounds like the key thing you're missing is to understand that a pointer is just another value, and it has a completely separate life from the thing it points to (or things, if you change it part way through its lifetime).

You say:

... the value of an immutable object can only be changed by also changing its location in memory, i.e. its reference (also known as its pointer).

This is wrong. An object doesn't own the pointers that point to it, nor is an object's memory location controlled or otherwise affected by any pointers to it.

So, the two NSString objects in your example (@"Bob" and @"Mike") are completely separate from the myName variable. They are also completely separate from each other. When you change myName to point to @"Mike" instead of pointing to @"Bob", you are not changing the NSString objects.


For completeness, I will note that garbage collectors make this more complex in that changes to pointers may affect the objects they point(ed) to. However, this is an implementation detail which should not affect the observable behaviour of the code.

John Bartholomew
  • 1,620
  • 12
  • 12
4

I think you feel lost, because you're mixing two concepts: object itself and variable name bound to that object.

Immutable objects cannot be changed. Period. However, variable name (symbol) bound to an immutable object, can modified to be bound to another immutable object.

In other words, what you did in these two lines was:

  1. create immutable string object with value "Bob"
  2. bind symbol myName to that object
  3. create immutable string object with value "Mike"
  4. bind symbol myName to that object
vartec
  • 20,760
  • 1
  • 52
  • 98
2

Your your type is not an NSString, it is a "pointer to an NSString", which is not immutable. I know nothing of objective C, but I'm guessing in your example that @"Mike" is creating a new instance of NSString and assigning it to the pointer myName. So you haven't changed the object that myName was pointing to, just what it was pointing to.

0

Here's an example of a mutable object: an array of char in C:

char str[10];

I can change the contents of str to my heart's content (so long as it's no more than 10 characters). For it to be recognized as a string by the C string library functions, there has to be a trailing 0, so it can hold strings up to 9 characters in length:

strcpy(str, "hello"); // str now contains the string "hello\0"
strcpy(str, "world"); // str now contains the string "world\0"

str[0] = 'W';         // str now contains "World\0"

und so weiter.

Contrast this with a string object in Java:

String foo = "Hello";

The string instance (the chunk of memory that contains the characters 'H', 'e', 'l', 'l', and 'o') cannot be modified; I cannot alter any of the contents of that string. When you write something like

foo = foo + " World";

you're not appending " World" to the end of the "Hello" instance; you are creating a new instance, copying "Hello World" to it, and updating foo to refer to that new string instance.

foo does not itself contain the string instance; it only refers to that instance (similar to a pointer in C or Obj-C), hence why types like String are called reference types.

John Bode
  • 10,826
  • 1
  • 31
  • 43