Ruby 什么';模块中@和@的区别是什么?

Ruby 什么';模块中@和@的区别是什么?,ruby,Ruby,假设模块是包含的,而不是扩展的,那么模块实例变量和类变量之间的区别是什么 我看不出两者有什么区别 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 我一直在一个模块中使用@as@,最近我看到其他代码在一个模块中使用@as@。然后我想我可能用错了 由于无法实例化模块,因此模块的@和@之间必须没有

假设模块是包含的,而不是扩展的,那么模块实例变量和类变量之间的区别是什么

我看不出两者有什么区别

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
我一直在一个模块中使用@as@,最近我看到其他代码在一个模块中使用@as@。然后我想我可能用错了

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

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

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

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

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

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

下面是一篇关于这方面的好文章

我发现,在谈到如何在模块中创建类变量时,“它们是本机支持的。”甚至说“类变量”这个名称是误导性的,因为类只是具有一些额外功能的模块


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

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

module A
  @@a = 5
end

class B
  include A
  puts @@a # => 5
end
同时,实例变量属于
self
。当您将模块
A
包含到类
B
中时,
A
self
对象与B的
self
对象不同,因此您将无法在它们之间共享实例变量

module A
  @a = 5
end

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

我对Ruby相当陌生,但为什么要定义一个返回实例变量的类/模块级方法呢?如果该方法处理实例变量,那么它不应该是一个实例方法,因此定义为“def foo”而不是“def self.foo”?不要使用类变量。最好不要学它们。它们本质上是有缺陷的,不提供任何实例变量所不能提供的功能。我真诚地希望它们从Ruby 2中删除。0@JoshuaCheek:那怎么办?Ruby 2.0应该与Ruby 1.9向后兼容,那么您打算如何在不破坏向后兼容性的情况下删除现有功能?@JörgWMittag不知道他们计划向后兼容。我希望他们能利用这个机会来删除和添加。事实上,如果你是向后兼容的,为什么要做一个2.0呢?这不只是1.10或1.11吗?他们现在不能制作1.10,原因与上次无法制作1.10的原因相同:因为太多脚本依赖于
RUBY\u VERSION>“1.6”
(或类似的东西)工作。而神话般的“Ruby 2.0”的功能集在近十年来一直被广泛讨论,以至于以任何不同的版本号发布该功能集都会导致巨大的混乱。在1.9开发周期中,2.0将是向后兼容的。Matz明确表示,他希望在1.9中最大化破损,以便在2.0中最小化破损。这是一个非常好的答案。因此,可以从包含模块的实例访问@@。但是@是不可访问的,对吗?是的,您也可以注意到继承的相同行为,例如父/子类可以共享@,而不是@(如果我们谈论的是类的作用域,而不是它的对象)。