9

Assuming a module is included, not extended, what's difference between module instance variable and class variable?

I do not see any difference between two.

module M
  @foo = 1
  def self.foo
    @foo
  end
end
p M.foo

module M
  @@foo = 1
  def self.foo
    @@foo
  end
end
p M.foo

I have been using @ as @@ within a module, and I recently saw other codes are using @@ within a module. Then I thought I might have been using it incorrectly.

Since we cannot instantiate a module, there must be no difference between @ and @@ for a module. Am I wrong?

----------------------- added the following --------------------

To answer some of questions on comments and posts, I also tested the following.

module M
  @foo = 1
  def self.bar
    :bar
  end

  def baz
    :baz
  end
end

class C
  include M
end

p [:M_instance_variabies, M.instance_variables] # [@foo]
p [:M_bar, M.bar] # :bar

c = C.new
p c.instance_variables
p [:c_instance_variabies, c.instance_variables] # []
p [:c_baz, c.baz] :baz
p [:c_bar, c.bar] # undefined method

When you include a module within a class, module class variables and class methods are not defined in a class.

allenhwkim
  • 27,270
  • 18
  • 89
  • 122
  • I am fairly new to Ruby, but why would you define a Class/Module level method that returns an instance variable? If the method is dealing with instance variables, shouldn't it be an instance method, thus defined as "def foo" rather than "def self.foo"? – Mark Sherretta Sep 10 '12 at 19:44
  • Don't use class variables. It's best to just not even learn learn them. They are inherently buggy and don't offer anything you can't do with instance variables. I sincerely hope they are removed from Ruby 2.0 – Joshua Cheek Sep 10 '12 at 23:26
  • @JoshuaCheek: How would that work? Ruby 2.0 is supposed to be backwards compatible with Ruby 1.9, so how do you propose to remove an existing feature without breaking backwards compatibility? – Jörg W Mittag Sep 11 '12 at 00:14
  • @JörgWMittag Didn't know they were planning backwards compatibility. I was hoping they'd use the occasion to remove as well as add. In fact, why make a 2.0 if you're backwards compatible? Isn't that just a 1.10 or 1.11? – Joshua Cheek Sep 11 '12 at 02:20
  • They can't make a 1.10 now for the same reason that they couldn't make a 1.10 the last time: because too many scripts depend on `RUBY_VERSION > '1.6'` (or something like that) to work. And the feature set of the mythical "Ruby 2.0" has been so widely discussed over almost a decade now that releasing that feature set under any different version number would lead to massive confusion. And that 2.0 would be backwards-compatible has already been documented during the 1.9 development cycle. Matz explicitly said that he wanted to maximize breakage in 1.9 in order to minimize breakage in 2.0. – Jörg W Mittag Sep 11 '12 at 10:31

3 Answers3

6

Class variables can be shared between modules and classes where these modules are included.

module A
  @@a = 5
end

class B
  include A
  puts @@a # => 5
end

Meanwhile, instance variables belong to self. When you include module A into class B, self object of A is not the same as self object of B, therefore you will not be able to share instance variables between them.

module A
  @a = 5
end

class B
  include A
  puts @a # => nil
end
hs-
  • 1,016
  • 9
  • 17
  • this is a very good answer. so @@ is accessbile from instances that includes the module. but @ is not accessible, right? – allenhwkim Sep 10 '12 at 20:26
  • yes, you can also notice the same behavior with inheritance, e.g. parent/child classes can share @@, and not @ (if we are talking about class's scope, not its object). – hs- Sep 10 '12 at 20:38
3

@@ refers to class variable and @ refers to instance variable. While using this with module makes big difference. When you include a module you add class methods to your class while extending add instance methods to your class

Following is a nice article on this

http://railstips.org/blog/archives/2006/11/18/class-and-instance-variables-in-ruby/

maximus ツ
  • 7,949
  • 3
  • 25
  • 54
0

I found this SO post that talks about how to create class variables in modules, "they are supported natively." One commenter even says the name 'class variable' is misleading since classes are just modules with a few extra powers.

All I'm sure of is nearly every article I've read about class variables thinks they're evil and to avoid them at all costs because of the weird inheritance issues you can encounter.

Community
  • 1
  • 1
lyonsinbeta
  • 919
  • 6
  • 25