A variable prefixed with @
is an instance variable, while one prefixed with @@
is a class variable. Check out the following example; its output is in the comments at the end of the puts
lines:
class Test @@shared = 1 def value @@shared end def value=(value) @@shared = value end end class AnotherTest < Test; end t = Test.new puts "t.value is #{t.value}" # 1 t.value = 2 puts "t.value is #{t.value}" # 2 x = Test.new puts "x.value is #{x.value}" # 2 a = AnotherTest.new puts "a.value is #{a.value}" # 2 a.value = 3 puts "a.value is #{a.value}" # 3 puts "t.value is #{t.value}" # 3 puts "x.value is #{x.value}" # 3
You can see that @@shared
is shared between the classes; setting the value in an instance of one changes the value for all other instances of that class and even child classes, where a variable named @shared
, with one @
, would not be.
[Update]
As Phrogz mentions in the comments, it’s a common idiom in Ruby to track class-level data with an instance variable on the class itself. This can be a tricky subject to wrap your mind around, and there is plenty of additional reading on the subject, but think about it as modifying the Class
class, but only the instance of the Class
class you’re working with. An example:
class Polygon class << self attr_accessor :sides end end class Triangle < Polygon @sides = 3 end class Rectangle < Polygon @sides = 4 end class Square < Rectangle end class Hexagon < Polygon @sides = 6 end puts "Triangle.sides: #{Triangle.sides.inspect}" # 3 puts "Rectangle.sides: #{Rectangle.sides.inspect}" # 4 puts "Square.sides: #{Square.sides.inspect}" # nil puts "Hexagon.sides: #{Hexagon.sides.inspect}" # 6
I included the Square
example (which outputs nil
) to demonstrate that this may not behave 100% as you expect; the article I linked above has plenty of additional information on the subject.
Also keep in mind that, as with most data, you should be extremely careful with class variables in a multithreaded environment, as per dmarkow’s comment.