A Class
isn't truly immutable if any of this children references aren't immutable as well.
If your root Class
has final
references to all its instance variables and all those instance variables are immutable as well as all their children following this same restriction then you can say the root Class
is immutable.
If any of the children references are non-final
or any of the children instances are mutable then the containing Class
is not immutable.
It doesn't matter about the internal immutablity whatever that means is anyone's guess, all that matters is that the public contract to the class immutability is kept. You can't have partial immutability anymore than you can be partially dead. Your class is either immutable or it isn't. And it isn't if any of its referred to classes or their classes, etc. are mutable.
If you have a graph and any of the members of the graph are mutable you can't deterministically say that you have an immutable state. Concurrency guarantees go out the window, .equals()
and .hashCode()
become non-deterministic and simple to test cloning and serializing go out the window as well.
If anything breaks this immutability contract you lose all the benefits of trying to maintain this immutability contract.
Simpler concurrency issues is a main motivational force of immutability.
Having side effect free code helps with predictability and maintainability. Since you don't have to wonder where things are getting mutated in the call tree because you know they can't be mutated.
Performance is another less important factor, in Java the JVM can make some highly optimized decisions about caching and other factors if it knows data can't change state. It does provide important hints to the compiler at compile time and the JIT algorithms at runtime.
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.
Best Answer
No! Do mind that fact - it is the key in understanding the point of immutable objects.
No, it hasn't. You have a different object with a different value in this place in the code.
But any other part of the code which had a reference to the original object still has that reference to that object with the original value.
Immutability is good because it prevents you from making a change to an object and having that change affect a completely different part of the code which wasn't written with the possibility in mind that the objects it operates on could be changed somewhere else (very little code is really written to cope with that).
This is particularly useful with multithreaded code (where a change done by a different thread could happen in between the operations of a single line of code), but even single-threaded code is much easier to understand when methods you call can't change the objects you pass into them.