Class instance variables vs class variables

I’m trying to understand the difference between “class instance”
variables (@var defined at class level) and “class” variables (@@var),
and when to use each. It seems like they are the same, except that
“class” variables can be referenced from instance methods. Is that
correct?

class A
@class_instance_var = 1
@@class_var = 2

def self.show_class_instance
puts “class instance variable #{@class_instance_var}”
end

def show_class_var
puts “class variable #{@class_var}”
end
end

a = A.new
A.show_class_instance
a.show_class_var

@Dave,

I think the key to understand
*instant variable
*class variable
is to look very hard at the prefix “instant” and “class”, which really
mean that @var belongs to an instant! @@var belongs to a class! But what
the heck would be the instant and class where they belong to, here comes
an example may enlighten you:

class Foo
@a = 1
class << self
attr_reader :a
end
def self.get_a # this is actually the same thing as above
@a
end

@@b = 1
def get_b
@@b
end
def self.get_b
@@b
end
end

class Bar < Foo
end

Foo.a # => 1
Foo.get_a # => 1

Bar.a # => nil
Bar.get_a # => nil

Bar.get_b # => 1
Bar.new.get_b # => 1

Hope it helps!

Webber had a great example, but for those who still don’t get it. A
class variable is a variable accessible by the parent class (in this
case Foo) and all of its descendants (Bar in this example).

class Foo
  @@five = 5 # Accessible by all descendants.
end

class Bar < Foo
  puts @@five # Bar, as a descendant, has access to @@five.
end

An instance variable is a variable accessible by a specific instance.
An instance is a specific object (Foo, Bar, Fixnum, are all specific
“instances”). So an instance variable defined in Bar is only available
to that instance (Bar).

class Foo
  @five = 5 # Accessible by ONLY Foo.
end

class Bar < Foo
  puts @five # Returns nil as @five is only accessible by Foo.
end

Hi,

On a practical note: I think you should generally avoid using class
variables. Because they are shared by all descendent classes and
objects, it’s almost impossible to keep them under control. Any
object of the inheritance chain may (accidentally) overwrite them and
break the code.

If you really need shared variables, you should probably encapsulate
them in a shared object:

Shared = Struct.new :x, :y

class A
@@shared = Shared.new 1, 2
def x
@@shared.x
end
def x= value
@@shared.x = value
end
end

B = Class.new A

a, b = A.new, B.new
puts a.x
b.x = 4
puts a.x

As you can see, the descendent classes and objects don’t have direct
access to x and y. They have to use the reader methods and writer
methods of @@shared. This allows you to limit access, catch erroneous
values etc.

Jacques