@@variable在Ruby中是什么意思?

时间:2021-02-04 22:34:40

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可以说它是一个全局变量,因此全局变量可以被全局访问