From: Josh Cheek Date: 2010-04-15T10:35:44+09:00 Subject: Re: Is there a way to make class and object constants in Ruby? --000e0cd112d647df6404843c837b Content-Type: text/plain; charset=ISO-8859-1 On Wed, Apr 14, 2010 at 8:00 PM, Xeno Campanoli wrote: > I am reading up in other areas, and it occurs to me much of the items I > have as class and object variables really should be constants, but ideally > still in the class or object context. Is there a way to do this? > > xc > -- > "It's the preponderance, stupid!" - Professor Stephen Schneider, IPCC > member > > Variables that begin with capital letters are constants initial_constants = Module.constants class MyClass MY_FAVOURITE_NUMBER = 12 MyFavouriteNumber = 12 end Module.constants - initial_constants # => [:MyClass] MyClass.constants # => [:MY_FAVOURITE_NUMBER, :MyFavouriteNumber] So you can see that classes are already constants, and an example of how to create constants within a class. In Ruby, this really means that the reference may not be changed (or at least you will be warned if you try to do so), not that the object being referenced may not be mutated. class MyClass MyFavouriteNumber = 12 MyFavouriteNumber = 13 # !> already initialized constant MyFavouriteNumber MyFavouriteNumber # => 13 end If you change your constant, you will know, it will warn you (ie, it won't happen by accident). If your code breaks because of this... well... you'll have a pretty good idea where to look. While Ruby is dynamic enough to make such a change, it is not something you should do. If you need to change your constants, then they shouldn't be constants. If you really need your data to not change, to the point where you don't even want to allow yourself the opportunity to do so, you can freeze it, and it will throw an exception class MyClass MyFavouriteWord = "ambivalent" MyFavouriteWord << 'l' MyFavouriteWord # => "ambivalentl" MyFavouriteWord.freeze MyFavouriteWord << 'y' MyFavouriteWord # => end # ~> -:6:in `': can't modify frozen string (RuntimeError) # ~> from -:1:in `
' But as far as I am aware, there is no way to recursively free any references it has (probably a good thing, you could recursively freeze your entire program) class MyClass SomeArray = [ 'abc' , 'def' ].freeze SomeArray # => ["abc", "def"] begin SomeArray << 'ghi' rescue => e e # => # end SomeArray.last # => "def" SomeArray.last << 'ghi' SomeArray.last # => "defghi" end Generally, constants are used for data that should be hard coded in, you use a constant so that you can easily change it later, like using a macro in C. You can then drop it into your code, and it is replaced with the actual value (you can redefine macros too). And they are also used for keeping important references, like the constant STDIN. We can change the global we use as stdin, but we don't want to lose track the actual stdin, so we keep it in the constant. STDIN # => #> $stdin # => #> $stdin = DATA # => # gets # => "this is the data\n" $stdin = STDIN # => #> __END__ this is the data --000e0cd112d647df6404843c837b--