Does above code mean @@states
is frozen?
Yes (sort-of). You called .freeze
on the object, so the object is frozen. I.e. technically the "frozen" thing is the object referenced by the variable, not the variable itself:
[1] pry(main)> x = "hello".freeze
=> "hello"
[2] pry(main)> x.frozen?
=> true
[3] pry(main)> x = "world"
=> "world"
[4] pry(main)> x.frozen?
=> false
Is @@states
re-assignable then how?
There's no "public interface" to change the variable, but you can do it via meta-programming:
Test.class_variable_set('@@states', 'CHANGED!')
Is writing @states
and @@states
same in class methods?
No. There's a subtle difference between an instance variable in a class and a class variable. For example, see this answer for a more detailed explanation.
If @@states
is not-frozen or re-assignable then how can I lock @@states once it is set so that it is not re-assignable?
You can't make it impossible to change/reassign anything in ruby; the best you can do is make it very awkward -- i.e. you have to write something "hacky" to change it.
In other words, you can remove any "public interface" and make the object frozen (which is exactly what you've done already), but - by the nature of ruby being a dynamic language with powerful meta-programming - there's always going to be some back-door way of changing a variable if you're really determined. For instance, see this library.
This isn't unique to ruby -- for example, it's possible to change constants in C/C++ by using pointers.