What are Ruby variables preceded with double at signs (@@
)? My understanding of a variable preceded with an at sign is that it is an instance variable, like this in PHP:
什么是Ruby变量前面有双符号(@@)?我对以@开头的变量的理解是它是一个实例变量,如PHP中所示:
PHP version
PHP版本
class Person {
public $name;
public function setName($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
Ruby equivalent
Ruby等效
class Person
def set_name(name)
@name = name
end
def get_name()
@name
end
end
What does the double at sign @@
mean, and how does it differ from a single at sign?
@@双@是什么意思?它和单@有什么区别?
5 个解决方案
#1
198
A variable prefixed with @
is an instance variable, while one prefixed with @@
is a class variable. Check out the following example; its output is in the comments at the end of the puts
lines:
一个带有@的变量是一个实例变量,而一个前缀@@是一个类变量。查看以下示例;它的输出在put行末尾的注释中:
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
You can see that @@shared
is shared between the classes; setting the value in an instance of one changes the value for all other instances of that class and even child classes, where a variable named @shared
, with one @
, would not be.
可以看到@@shared在类之间共享;在一个类的实例中设置值将更改该类的所有其他实例的值,甚至子类的所有实例的值,其中一个名为@shared的变量将不会是@。
[Update]
(更新)
As Phrogz mentions in the comments, it's a common idiom in Ruby to track class-level data with an instance variable on the class itself. This can be a tricky subject to wrap your mind around, and there is plenty of additional reading on the subject, but think about it as modifying the Class
class, but only the instance of the Class
class you're working with. An example:
正如Phrogz在评论中提到的,在Ruby中,使用类本身的实例变量跟踪类级数据是一种常见的习惯用法。这可能是一个复杂的主题,您需要把注意力集中在这个主题上,有很多关于这个主题的额外阅读,但是可以把它看作是修改类,而只是修改正在处理的类的实例。一个例子:
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
I included the Square
example (which outputs nil
) to demonstrate that this may not behave 100% as you expect; the article I linked above has plenty of additional information on the subject.
我引入了方阵示例(输出nil),以证明它的行为可能不像您期望的那样100%;我上面链接的文章有很多关于这个主题的附加信息。
Also keep in mind that, as with most data, you should be extremely careful with class variables in a multithreaded environment, as per dmarkow's comment.
还要记住,与大多数数据一样,在多线程环境中处理类变量应该非常小心,正如dmarkow的评论所言。
#2
33
@
- Instance variable of a class@@
- Class variable, also called as static variable in some cases
@ -一个类@@ -类变量的实例变量,在某些情况下也称为静态变量
A class variable is a variable that is shared amongst all instances of a class. This means that only one variable value exists for all objects instantiated from this class. If one object instance changes the value of the variable, that new value will essentially change for all other object instances.
类变量是在类的所有实例*享的变量。这意味着只有一个变量值存在于从这个类实例化的所有对象中。如果一个对象实例改变了变量的值,那么这个新值对于所有其他对象实例都将发生本质上的改变。
Another way of thinking of thinking of class variables is as global variables within the context of a single class. Class variables are declared by prefixing the variable name with two @
characters (@@
). Class variables must be initialized at creation time
另一种考虑类变量的方法是将全局变量放在一个类的上下文中。类变量通过在变量名前面加上两个@字符(@)来声明。必须在创建时初始化类变量
#3
9
@@
denotes a class variable, i.e. it can be inherited.
@@表示一个类变量,即它可以被继承。
This means that if you create a subclass of that class, it will inherit the variable. So if you have a class Vehicle
with the class variable @@number_of_wheels
then if you create a class Car < Vehicle
then it too will have the class variable @@number_of_wheels
这意味着如果您创建该类的子类,它将继承该变量。如果你有一个类车辆,它有一个类变量@number_of_wheels如果你创建一个类车< Vehicle那么它也有一个类变量@number_of_wheels
#4
1
@ and @@ in modules also work differently when a class extends or includes that module.
当一个类扩展或包含该模块时,模块中的@和@也以不同的方式工作。
So given
鉴于
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
Then you get the outputs below shown as comments
然后您将得到如下所示的输出作为注释
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
So use @@ in modules for variables you want common to all their uses, and use @ in modules for variables you want separate for every use context.
因此,在模块中使用@来表示所有的变量,并在模块中使用@来表示每个使用上下文需要分离的变量。
#5
-1
@ =instance variable where as @@=class variable
@=实例变量,其中@=类变量
the instance variable is like, which is share with instance/objects of a class in order to access the instance variable we need to define the setters and getters for that instance variable
实例变量类似于,它与类的实例/对象共享,以便访问我们需要为该实例变量定义setter和getter的实例变量
whereas the class variable is like,which is shared among all the instances/objects of a class or in other words u can say that it is a global variable,so global variable can be accessed globally
类变量是这样的,它在类的所有实例/对象之间共享,换句话说,u可以说它是一个全局变量,因此全局变量可以被全局访问
#1
198
A variable prefixed with @
is an instance variable, while one prefixed with @@
is a class variable. Check out the following example; its output is in the comments at the end of the puts
lines:
一个带有@的变量是一个实例变量,而一个前缀@@是一个类变量。查看以下示例;它的输出在put行末尾的注释中:
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
You can see that @@shared
is shared between the classes; setting the value in an instance of one changes the value for all other instances of that class and even child classes, where a variable named @shared
, with one @
, would not be.
可以看到@@shared在类之间共享;在一个类的实例中设置值将更改该类的所有其他实例的值,甚至子类的所有实例的值,其中一个名为@shared的变量将不会是@。
[Update]
(更新)
As Phrogz mentions in the comments, it's a common idiom in Ruby to track class-level data with an instance variable on the class itself. This can be a tricky subject to wrap your mind around, and there is plenty of additional reading on the subject, but think about it as modifying the Class
class, but only the instance of the Class
class you're working with. An example:
正如Phrogz在评论中提到的,在Ruby中,使用类本身的实例变量跟踪类级数据是一种常见的习惯用法。这可能是一个复杂的主题,您需要把注意力集中在这个主题上,有很多关于这个主题的额外阅读,但是可以把它看作是修改类,而只是修改正在处理的类的实例。一个例子:
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
I included the Square
example (which outputs nil
) to demonstrate that this may not behave 100% as you expect; the article I linked above has plenty of additional information on the subject.
我引入了方阵示例(输出nil),以证明它的行为可能不像您期望的那样100%;我上面链接的文章有很多关于这个主题的附加信息。
Also keep in mind that, as with most data, you should be extremely careful with class variables in a multithreaded environment, as per dmarkow's comment.
还要记住,与大多数数据一样,在多线程环境中处理类变量应该非常小心,正如dmarkow的评论所言。
#2
33
@
- Instance variable of a class@@
- Class variable, also called as static variable in some cases
@ -一个类@@ -类变量的实例变量,在某些情况下也称为静态变量
A class variable is a variable that is shared amongst all instances of a class. This means that only one variable value exists for all objects instantiated from this class. If one object instance changes the value of the variable, that new value will essentially change for all other object instances.
类变量是在类的所有实例*享的变量。这意味着只有一个变量值存在于从这个类实例化的所有对象中。如果一个对象实例改变了变量的值,那么这个新值对于所有其他对象实例都将发生本质上的改变。
Another way of thinking of thinking of class variables is as global variables within the context of a single class. Class variables are declared by prefixing the variable name with two @
characters (@@
). Class variables must be initialized at creation time
另一种考虑类变量的方法是将全局变量放在一个类的上下文中。类变量通过在变量名前面加上两个@字符(@)来声明。必须在创建时初始化类变量
#3
9
@@
denotes a class variable, i.e. it can be inherited.
@@表示一个类变量,即它可以被继承。
This means that if you create a subclass of that class, it will inherit the variable. So if you have a class Vehicle
with the class variable @@number_of_wheels
then if you create a class Car < Vehicle
then it too will have the class variable @@number_of_wheels
这意味着如果您创建该类的子类,它将继承该变量。如果你有一个类车辆,它有一个类变量@number_of_wheels如果你创建一个类车< Vehicle那么它也有一个类变量@number_of_wheels
#4
1
@ and @@ in modules also work differently when a class extends or includes that module.
当一个类扩展或包含该模块时,模块中的@和@也以不同的方式工作。
So given
鉴于
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
Then you get the outputs below shown as comments
然后您将得到如下所示的输出作为注释
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
So use @@ in modules for variables you want common to all their uses, and use @ in modules for variables you want separate for every use context.
因此,在模块中使用@来表示所有的变量,并在模块中使用@来表示每个使用上下文需要分离的变量。
#5
-1
@ =instance variable where as @@=class variable
@=实例变量,其中@=类变量
the instance variable is like, which is share with instance/objects of a class in order to access the instance variable we need to define the setters and getters for that instance variable
实例变量类似于,它与类的实例/对象共享,以便访问我们需要为该实例变量定义setter和getter的实例变量
whereas the class variable is like,which is shared among all the instances/objects of a class or in other words u can say that it is a global variable,so global variable can be accessed globally
类变量是这样的,它在类的所有实例/对象之间共享,换句话说,u可以说它是一个全局变量,因此全局变量可以被全局访问