2

I have the following variable

CONSTANT =5 

I wanted to test how Constants work in Ruby and was surprised to find out the following:

CONSTANT = 6

..results in CONSTANT actually being overwritten with a warning. I come from a java background where constants are just that, constant, thus I am a little confused as how Ruby accomplishes things.

My question is if there is any way to mimic javas final keyword in Ruby, thus not allowing a user to change the value of a variable?

JmanxC
  • 377
  • 2
  • 16
  • I don't think there are equivalents to Java constants in Ruby. – Andrew Li Jun 14 '16 at 00:12
  • Reflection in Ruby is effortless and pervasive, and it would not be Ruby any more without it; and it is trivial to ignore any access controls using it. There is also no way of preventing people from doing `class String; def +(o); "NO!" end end`.The Ruby way is: don't do stupid and you'll be fine. – Amadan Jun 14 '16 at 04:01

1 Answers1

3

Like a lot of things in Ruby there is no "final", things are inherently dynamic and absolutely preventing people from doing things is never really going to happen. You can just make it difficult.

The one thing to note is in Ruby there's a difference between immutable and constant. A constant is a variable which will generate a warning when reassigned, that's all, and there's nothing to prevent you from modifying it. To prevent modifications you must "freeze" the object in question, though as with all things in Ruby, this is just a request that can be ignored by the object.

Typically you'll see code like this:

ADMIN_USER_TYPE = 'Admin'.freeze

Or this:

USER_TYPES = %w[
  Admin
].freeze

The freeze call is to catch cases where the list might be mangled by some method by accident. It does not absolutely prevent this, it's more of a safety measure. Consider this code:

def user_labels(types)
  types.map! { |t| [ t, t.downcase.to_sym ] }
end

Here a mistaken map! call would have the effect of rewriting the original array. In cases where you're calling it with a throw-away argument this is fine:

user_labels(%w[ Admin Test ])

When you're using the constant you'll permanently modify it, and that will cause it to get modified over and over each time it's called, creating a mess. The freeze flag trips a warning here and prevents that.

So the short answer is: No. The long answer is you have to be disciplined, the language will not prevent you from doing this if you're sufficiently determined. Pay attention to warnings and treat them seriously.

tadman
  • 208,517
  • 23
  • 234
  • 262