Ruby中的@@variables是什么意思?

在符号( @@ )前面加上双引号的Rubyvariables是什么? 我对一个带有at符号的variables的理解是,它是一个实例variables,就像这样在PHP中:

PHP版本

 class Person { public $name; public function setName($name) { $this->name = $name; } public function getName() { return $this->name; } } 

ruby相当

 class Person def set_name(name) @name = name end def get_name() @name end end 

@@是什么意思,这与标志中的单个标志有什么不同?

@为前缀的variables是一个实例variables ,而以@@为前缀的variables是一个类variables 。 看看下面的例子。 它的输出是在puts行末尾的注释中:

 class Test @@shared = 1 def value @@shared end def value=(value) @@shared = value end end class AnotherTest < Test; end t = Test.new puts "t.value is #{t.value}" # 1 t.value = 2 puts "t.value is #{t.value}" # 2 x = Test.new puts "x.value is #{x.value}" # 2 a = AnotherTest.new puts "a.value is #{a.value}" # 2 a.value = 3 puts "a.value is #{a.value}" # 3 puts "t.value is #{t.value}" # 3 puts "x.value is #{x.value}" # 3 

你可以看到@@shared被类共享。 在一个实例中设置值会更改该类的所有其他实例甚至是子类的值,其中名为@shared的variables与@不会同时存在。

[更新]

正如Phrogz在评论中提到的那样,在Ruby中用实例variables跟踪类级数据是常见的习惯用法。 这可能是一个棘手的问题,包装你的头脑,有很多额外的阅读主题,但认为它是修改Class类,但只有您正在使用的Class类的实例。 一个例子:

 class Polygon class << self attr_accessor :sides end end class Triangle < Polygon @sides = 3 end class Rectangle < Polygon @sides = 4 end class Square < Rectangle end class Hexagon < Polygon @sides = 6 end puts "Triangle.sides: #{Triangle.sides.inspect}" # 3 puts "Rectangle.sides: #{Rectangle.sides.inspect}" # 4 puts "Square.sides: #{Square.sides.inspect}" # nil puts "Hexagon.sides: #{Hexagon.sides.inspect}" # 6 

我列举了Square例子(输出nil )来certificate这可能不像你预期的那样100% 我上面链接的文章有很多关于这个主题的额外信息。

另外请记住,与大多数数据一样,在multithreading环境中 ,您应该非常小心类variables,按照dmarkow的评论。

@ – 一个类的实例variables
@@ – 类variables,在某些情况下也称为静态variables

类variables是在类的所有实例之间共享的variables。 这意味着从这个类实例化的所有对象只存在一个variables值。 如果一个对象实例改变了variables的值,那么这个新值将会在所有其他对象实例上发生变化。

另一种思考类variables的方法是在单个类的上下文中作为全局variables。 类variables是通过在variables名前加两个@字符( @@ )来声明的。 类variables必须在创build时初始化

@@表示一个类variables,即它可以被inheritance。

这意味着如果您创build了该类的子类,它将inheritance该variables。 所以如果你有一个类的variables@@number_of_wheels那么如果你创build一个class Car < Vehicle那么它也会有类variables@@number_of_wheels

@ =实例variables,其中@@ =类variables

实例variables是类似的,它与一个类的实例/对象共享,以便访问实例variables,我们需要为该实例variables定义setter和getters

而类variables是类似的,它是在一个类的所有实例/对象之间共享的,换句话说,你可以说它是一个全局variables,所以全局variables可以被全局访问

当模块扩展或包含该模块时,模块中的@和@@也会有不同的工作方式。

如此给予

 module A @a = 'module' @@a = 'module' def get1 @a end def get2 @@a end def set1(a) @a = a end def set2(a) @@a = a end def self.set1(a) @a = a end def self.set2(a) @@a = a end end 

然后你得到下面显示的输出作为注释

 class X extend A puts get1.inspect # nil puts get2.inspect # "module" @a = 'class' @@a = 'class' puts get1.inspect # "class" puts get2.inspect # "module" set1('set') set2('set') puts get1.inspect # "set" puts get2.inspect # "set" A.set1('sset') A.set2('sset') puts get1.inspect # "set" puts get2.inspect # "sset" end class Y include A def doit puts get1.inspect # nil puts get2.inspect # "module" @a = 'class' @@a = 'class' puts get1.inspect # "class" puts get2.inspect # "class" set1('set') set2('set') puts get1.inspect # "set" puts get2.inspect # "set" A.set1('sset') A.set2('sset') puts get1.inspect # "set" puts get2.inspect # "sset" end end Y.new.doit 

因此,在模块中使用@@作为您希望在其所有用途中共同使用的variables,并且在模块中使用@表示要在每个使用上下文中分开的variables。