Question

I have a class with an instance variable var.
I don't want the variable to be modified / assigned to a value except when the object is created using a Class method.

isImmutable: aBoolean is the method to convert a mutable object to an immutable object and vice-versa.
Can someone please provide me the correct syntax to do it?

Was it helpful?

Solution 3

I implemented it using the code:

MyClass class>>classMethod: aValue

anObject := self new value:aValue.
anObject isImmutable: true.
^anObject.

OTHER TIPS

I haven't tried it, but I'm pretty certain that isImmutable won't do the trick. Assuming that does actually make an object immutable, it will make the object pointed to by the instVar immutable, not the instvar itself.

Your best bet is to simply not include a specific Mutator for the variable at all, but to instead set it at initialization time like this:

MyClass class>>newWithFoo: aFoo
   ^self basicNew initializeWithFoo: aFoo; yourself

MyClass>>initializeWithFoo: aFoo
   self initialize.
   foo := aFoo.

That way, the only way anyone outside the class itself can affect the variable is by creating a new instance by calling MyClass newWithFoo:

(Not counting using reflective methods like #instVarNamed:put: - there's pretty much nothing you can do about them, but anyone using them knows they're breaking the contract of the class anyway).

why do you want to make the object immutable? Isn't it enough to declare your API in a way that makes it obvious how to use the class and to not replace the instance variable?

One thing to keep in mind is that immutability operates at a single level in the object graph. Instance variables are a bit like a constant pointer in C++, the address cannot change, but the contents can change.
Here is a little example:

| a b |
a := Array with: 1.
b := Array with: a.
b beImmutable.
b at: 1 put: nil.
^b

Will end up with a NoModificationError, you cannot write any instance/indexed variable of b since b is immutable.
But you can write into the objects pointed by the instance/indexed variables of b:

| a b |
a := Array with: 1.
b := Array with: a.
b beImmutable.
a at: 1 put: 2.
^b

Will succeed, and b is now #(#(2)) instead of #(#(1))

You can also arrange to propagate the immutability further down the object graph if ever that's what you are after (but beware of cycles).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top