Create a gist now

Instantly share code, notes, and snippets.

Class Variables vs. Class Instance Variables
The "Class Variable" Method in class GuidProvider1 (the "@@" notation) is
simpler to use, but violates the principle that the object that owns a
variable is the only one who can directly read or modify it. That is, there
is no privacy or protection, in that there is no way the instances can be
prevented from reading and writing to the variable (for example, the 'next'
instance method does both).
In contrast, the "Class Instance Variable" single @ notation as shown in
GuidProvider2 behaves in a way that is consistent with instance variables in
other contexts (that is, within instance methods). The variables are not
readable directly, but instead must be explicitly exposed by providing a
class getter method. In the example, a getter but not a setter is
defined so that instances cannot directly modify the variable.
# "Class Variable" Method
class GuidProvider1
@@highest_seqno = 0
def next
@@highest_seqno += 1
def self.highest_seqno
guid_provider =
50.times { }
puts "Highest sequence number for GuidProvider1 is #{guid_provider.class.highest_seqno}"
# "Class Instance Variable" Method
class GuidProvider2
@highest_seqno = 0
class << self
attr_reader :highest_seqno
@highest_seqno += 1
def next
guid_provider =
5.times { }
puts "Highest sequence number is #{GuidProvider2.highest_seqno}"
puts "Can't write to it, this will throw an error because we defined a getter but not a setter:"
guid_provider.highest_seqno = 3

Kieth, another thing to be aware of is that @@ variables are not protected; that is, there is only one variable for the entire class heirarchy, and subclasses can freely modify it:

class Foo                                                                          
  @@foo = 1                                                                        
  def foo                                                                          

class FooBar < Foo                                                                 
  def next                                                                         
    @@foo += 1                                                                     
puts  # => 2

This is bad because it ignores any invariants that might be required for the parent class to behave correctly, and errors of this sort can be very hard to track down. @@class_variables have been on the "deprecated, avoid this" list for a long, long time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment