9

假设一个模块被包含,而不是扩展,模块实例变量和类变量有什么区别?

我看不出两者有什么区别。

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

我一直在模块中使用@ 作为@@,最近我看到其他代码在模块中使用@@。然后我想我可能用错了。

由于我们无法实例化模块,因此模块的 @ 和 @@ 之间必须没有区别。我错了吗?

----------------------- 添加了以下内容 --------------------

为了回答关于评论和帖子的一些问题,我还测试了以下内容。

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

当您在类中包含模块时,模块类变量和类方法未在类中定义。

4

3 回答 3

6

类变量可以在模块和包含这些模块的类之间共享。

module A
  @@a = 5
end

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

同时,实例变量属于self。当您将模块包含A到类B中时,self对象的A对象self与 B 的对象不同,因此您将无法在它们之间共享实例变量。

module A
  @a = 5
end

class B
  include A
  puts @a # => nil
end
于 2012-09-10T20:09:23.743 回答
3

@@ 指类变量,@ 指实例变量。虽然将它与模块一起使用会产生很大的不同。当您包含一个模块时,您将类方法添加到您的类,同时将添加实例方法扩展到您的类

以下是一篇不错的文章

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

于 2012-09-10T19:44:34.293 回答
0

我发现这篇 SO 帖子讨论了如何在模块中创建类变量,“它们是本机支持的。” 一位评论者甚至说“类变量”这个名称具有误导性,因为类只是具有一些额外功能的模块。

我可以肯定的是,我读过的几乎所有关于类变量的文章都认为它们是邪恶的,并且由于您可能会遇到奇怪的继承问题而不惜一切代价避免它们。

于 2012-09-10T19:46:30.770 回答