2

Here is my test program:

module Foo

  @@bar1 = "1" # static property of the module?

  class << self # open static section

    @bar2 = "2" # property in static section, should be static property?

    def func1 # static function
      puts "bar1: #{@@bar1}"
      puts "bar2: #{@bar2}"
    end
  end

end

Foo.func1

Which produces the output:

$ ruby test.rb
bar1: 1
bar2:

My question is, what is the difference between the declarations of bar1 and bar2?

I thought that

But, when they are printed out in func1, bar2 is not initialised. Why are they behaving differently?

Community
  • 1
  • 1
alksdjg
  • 1,019
  • 2
  • 10
  • 26

1 Answers1

3

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.

Aetherus
  • 8,720
  • 1
  • 22
  • 36