First, let's forget about the singleton class (class << self
) for a while.
Module/class variables (static variables) are not the same as module/class instance variables, as
A module/class variable is accessible from both the module/class and its instances, but a module/class instance variable is not.
class X
@@foo = 'foo' # a class variable
@bar = 'bar' # a class instance variable
def self.foo
@@foo
end
def self.bar
@bar
end
def foo
@@foo
end
def bar
@bar
end
end
X.foo #=> "foo"
X.bar #=> "bar"
X.new.foo #=> "foo"
X.new.bar #=> nil
Module/class variables are shared in the inheritance tree, but module/class instance variables are not.
class Parent
@@foo = 'foo in parent'
@bar = 'bar in parent'
def self.foo
@@foo
end
def self.bar
@bar
end
end
class Child < Parent
@@foo = 'foo in child'
@bar = 'bar in child'
end
Parent.foo #=> "foo in child"
Parent.bar #=> "bar in parent"
For this reason, using module/class variables is not recommended.
Let's talk a little more about the behavior of module/class instance variables.
In Ruby, modules and classes are objects, so they can have their own instance variables just like normal objects. These instance variables in modules/classes are called module/class instance variables.
In Ruby, an instance variable belongs ONLY to the host object. No other object can see it (at least without using meta programming tricks).
A class and an instance of that class are 2 different objects, so instances can't access class instance variables. A class and a subclass of it are 2 different objects, so they can't access class instance variable each other.
Finally, lets talk about the singleton class.
Every object has its singleton class. That singleton class has only one instance - the object.
Modules and classes are objects, so they can have their own singleton classes.
class << self
opens the singleton class of self
, which, in your code, is the module Foo
.
Note that a module/class and its singleton class are 2 different objects, so they don't share module/class instance variables. The module/class doesn't inherit the singleton class, neither does the singleton class inherit the module/class, so they don't share module/class variables, either.