在Ruby的类作用域中使用@variable正确吗?

在Ruby的类作用域中使用@variable正确吗?,ruby,Ruby,我经常看到ruby项目在ruby类的类作用域中使用实例变量@var 我认为在类方法中,应该使用类变量@var,而在实例方法中,应该使用实例变量@var 我想知道在类范围中使用@var是否正确 目前我知道在类作用域中使用实例变量和类变量的区别在于实例变量不能被子类继承。代码演示了差异 class Foo @bar = 8 @@bar2 = 10 def self.echo_bar p @bar end def self.echo_bar2 p @@bar2

我经常看到ruby项目在ruby类的类作用域中使用实例变量@var

我认为在类方法中,应该使用类变量@var,而在实例方法中,应该使用实例变量@var

我想知道在类范围中使用@var是否正确

目前我知道在类作用域中使用实例变量和类变量的区别在于实例变量不能被子类继承。代码演示了差异

class Foo
  @bar = 8
  @@bar2 = 10
  def self.echo_bar
    p @bar
  end

  def self.echo_bar2
    p @@bar2
  end
end

class Foo2 < Foo

end

Foo.echo_bar
Foo.echo_bar2

Foo2.echo_bar
Foo2.echo_bar2
# Result:
# 8
# 10
# nil
# 10
class-Foo
@巴=8
@@bar2=10
def self.echo_条
p@bar
结束
def self.echo_bar2
p@@bar2
结束
结束
类别Foo2
Ruby对象是:

  • 数据-实例变量和相关值的映射。请注意,实例变量是实例本身的私有变量
  • 行为-指向定义此实例响应的方法的类的指针。注意方法可以从父类继承
  • 类是Ruby中的一个对象。以书面形式:

    class Foo
      @bar = 8
      def self.get_bar
        @bar
      end
    end
    
    class FooChild < Foo
    end
    
    您将获得以下数据模型(不完全是这样,Foo的祖先及其特征类的层次结构已被删除):

    类作用域中的实例变量定义该类对象的私有数据。从上面的模型中,可以通过Foo的特征类中定义的实例方法以及其祖先链
    类、模块、对象、内核、BasicObject
    访问该实例变量。这些实例变量定义了一些与类对象
    Foo
    关联的数据

    以书面形式:

    class Foo
      @bar = 8
      def self.get_bar
        @bar
      end
    end
    
    class FooChild < Foo
    end
    

    实例变量在类内部定义,但在名为
    类实例变量的实例方法外部定义

    使用类实例变量和类变量的优势在于使用继承时。您也可以在子类中使用类实例变量,但这看起来很混乱

    这不完全是一种继承。Ruby实现有点棘手。Ruby中的实例变量是在赋值时创建的

    任何子类都可以更改共享类变量的值,但只会为特定类创建类实例变量。因此,请注意在类中变量需要什么行为

    和类变量相比,类实例变量的缺点是它们不能在实例方法内部使用。除此之外,您还可以将它们与常规实例变量混淆

      class Foo
        @class_instance_var_1 = 0
        @class_instance_var_2 = 0
        @@class_var = 10
    
        def initialize
          @class_instance_var_1 = 1 # cannot change it here
          @@class_var = 100
        end
    
        def self.change
          @class_instance_var_2 = 2 # can change here
          @@class_var = 200
        end
    
        def self.echo_var
          p 'class_instance_var_1=' + @class_instance_var_1.to_s
          p 'class_instance_var_2=' + @class_instance_var_2.to_s
          p 'class_var=' + @@class_var.to_s
        end
      end
    
      puts '--- initial status of Foo'
      Foo.echo_var
      puts '--- initialized Foo'
      Foo.new
      Foo.echo_var
      puts '--- changed Foo'
      Foo.change
      Foo.echo_var
    
      class Foo2 < Foo
        @class_instance_var_2 = 22 # can set here only but not in Foo
        @@class_var = 20 # can change here and everywhere
      end
    
      puts '--- after Foo2 implementation'
      puts '--- Foo'
      Foo.echo_var
      puts '--- Foo2'
      Foo2.echo_var
    
      class Foo3 < Foo2
        @class_instance_var_2 = 33 # can set here only but not in Foo
        @@class_var = 30 # can change here and everywhere
      end
    
      puts '--- after Foo3 implementation'
      puts '--- Foo'
      Foo.echo_var
      puts '--- Foo2'
      Foo2.echo_var
      puts '--- Foo3'
      Foo3.echo_var
    

    当然,这可能是正确的方法,这取决于上下文。在rails中,我几乎看到@var在类作用域中使用,可能只是因为@var看起来很难看?这与它的外表毫无关系。实例变量和类变量的语义完全不同,您无法交换它们。在Rails中,您将看不到类变量,因为首选
    class\u attribute
    (ActiveSupport定义的方法)<创建代码>class_属性
    是因为类变量在超类和子类之间共享,因此子类中对其值的修改也应用于超类,这是很少需要的。使用
    class\u属性
    可以避免这种影响最好使用
    singleton\u类
    而不是
    eigenclass
    ,因为甚至有一个方法具有该名称
      class Foo
        @class_instance_var_1 = 0
        @class_instance_var_2 = 0
        @@class_var = 10
    
        def initialize
          @class_instance_var_1 = 1 # cannot change it here
          @@class_var = 100
        end
    
        def self.change
          @class_instance_var_2 = 2 # can change here
          @@class_var = 200
        end
    
        def self.echo_var
          p 'class_instance_var_1=' + @class_instance_var_1.to_s
          p 'class_instance_var_2=' + @class_instance_var_2.to_s
          p 'class_var=' + @@class_var.to_s
        end
      end
    
      puts '--- initial status of Foo'
      Foo.echo_var
      puts '--- initialized Foo'
      Foo.new
      Foo.echo_var
      puts '--- changed Foo'
      Foo.change
      Foo.echo_var
    
      class Foo2 < Foo
        @class_instance_var_2 = 22 # can set here only but not in Foo
        @@class_var = 20 # can change here and everywhere
      end
    
      puts '--- after Foo2 implementation'
      puts '--- Foo'
      Foo.echo_var
      puts '--- Foo2'
      Foo2.echo_var
    
      class Foo3 < Foo2
        @class_instance_var_2 = 33 # can set here only but not in Foo
        @@class_var = 30 # can change here and everywhere
      end
    
      puts '--- after Foo3 implementation'
      puts '--- Foo'
      Foo.echo_var
      puts '--- Foo2'
      Foo2.echo_var
      puts '--- Foo3'
      Foo3.echo_var
    
    --- initial status of Foo
    "class_instance_var_1=0"
    "class_instance_var_2=0"
    "class_var=10"
    --- initialized Foo
    "class_instance_var_1=0"
    "class_instance_var_2=0"
    "class_var=100"
    --- changed Foo
    "class_instance_var_1=0"
    "class_instance_var_2=2"
    "class_var=200"
    --- after Foo2 implementation
    --- Foo
    "class_instance_var_1=0"
    "class_instance_var_2=2"
    "class_var=20"
    --- Foo2
    "class_instance_var_1="
    "class_instance_var_2=22"
    "class_var=20"
    --- after Foo3 implementation
    --- Foo
    "class_instance_var_1=0"
    "class_instance_var_2=2"
    "class_var=30"
    --- Foo2
    "class_instance_var_1="
    "class_instance_var_2=22"
    "class_var=30"
    --- Foo3
    "class_instance_var_1="
    "class_instance_var_2=33"
    "class_var=30"