【问题标题】:Class Level Instance Variables in RubyRuby 中的类级实例变量
【发布时间】:2014-10-23 07:41:30
【问题描述】:

请帮助我理解类级实例变量。

@@ 是一个类变量,相当于类实例中的实例变量(@)。

但是在类级别使用时,实例变量 (@) 是什么?如果它为类实例定义了一个定义,那么为什么不在初始化器中定义它呢?

class MyClass
  cattr_reader :class_variable

  def self.new_instance(cv, cliv, iv)
    @@class_variable = cv
    @class_level_instance_variable = cliv
    self.new(iv)
  end

  def initialize(iv)
    @instance_variable = iv
  end

  def use
    puts "class_var=#{self.class.class_variable.inspect}\ninst_var=#{@instance_variable.inspect}\ncliv=#{@class_level_instance_variable.inspect}"
  end
end

c = []
c << MyClass.new_instance(1,2,3)
c[0].use
c << MyClass.new_instance(4,5,6)
c[1].use
c << MyClass.new_instance(7,8,9)
c[2].use

c[0].use
c[1].use
c[2].use

【问题讨论】:

  • 当你在类级别设置实例变量时,它就变成了类实例变量,这与类变量略有不同(并不完全等同)。更多信息:railstips.org/blog/archives/2006/11/18/…
  • @Marek Lipka:所以,如果我理解正确,类级实例变量完全等同于预初始化的实例级实例变量,如果我在一个类方法中创建多个类实例,每个实例都变成用这个变量初始化。
  • 不,根本没有这样的行为。我的意思是类级别的实例变量是 regular 实例变量,但绑定到类对象(记住在 Ruby 中类也是对象)。
  • @Paul:你为什么不输入一些代码来说明你的意思?

标签: ruby class instance-variables class-variables


【解决方案1】:

在您的回答中,您没有输出类级别的实例变量。除了通常的语法 (@foo) 之外,还可以通过方法 (instance_variable_get(:@foo)) 访问实例变量。您可以使用此方法读取其他对象的实例变量,而不仅仅是self

这是您的代码的修改版本

require 'active_support/core_ext'

class MyClass
  cattr_reader :class_variable

  def self.new_instance(cv, cliv, iv)
    @@class_variable = cv
    @class_level_instance_variable = cliv
    self.new(iv)
  end

  def initialize(iv)
    @instance_variable = iv
  end

  def use
    puts "class_var=#{self.class.class_variable.inspect}"
    puts "class inst var: #{self.class.instance_variable_get(:@class_level_instance_variable)}"
    puts "inst_var=#{@instance_variable.inspect}"
  end
end

c = []
c << MyClass.new_instance(1,2,3)
c << MyClass.new_instance(4,5,6)
c << MyClass.new_instance(7,8,9)

c[0].use
c[1].use
c[2].use
# >> class_var=7
# >> class inst var: 8
# >> inst_var=3
# >> class_var=7
# >> class inst var: 8
# >> inst_var=6
# >> class_var=7
# >> class inst var: 8
# >> inst_var=9

看,class inst var 总是 8(就像 class var 总是 7)。这是因为您在进行所有修改后输出值。而且由于类级别的变量是共享的,所以最后的修改获胜。

c << MyClass.new_instance(7,8,9)

如果您要从初始化程序输出(就像在您的第一个代码版本中一样),您会看到不同的结果。

# >> class_var=1
# >> class inst var: 2
# >> inst_var=3
# >> class_var=4
# >> class inst var: 5
# >> inst_var=6
# >> class_var=7
# >> class inst var: 8
# >> inst_var=9

【讨论】:

  • 因此,类级实例变量提供了一种在子级之间进行通信的方式,因为它通过引用传递给每个实例。对吗?
  • 是的,它在类的所有实例之间共享。
【解决方案2】:

希望这个例子能解释@(实例)和@@(类)变量之间的区别。

class Animal
  @@total_count = 0

  def self.total_count
    @@total_count
  end

  def initialize
    @@total_count += 1
  end
end

class Cat < Animal
end

Animal.new
Animal.new
Cat.new

Animal.total_count # => 3
Cat.total_count # => 3

如您所见,@@ 变量在类及其子级之间共享。如果我真的想计算类的实例数,我必须使用以下代码。

class Animal
  class << self
    attr_accessor :total_count
  end

  @total_count = 0

  def self.total_count
    @total_count
  end

  def initialize
    self.class.total_count += 1
  end
end

class Cat < Animal
  @total_count = 0
end

Animal.new
Animal.new
Cat.new

Animal.total_count # => 2
Cat.total_count # => 1

【讨论】:

    猜你喜欢
    • 2012-05-30
    • 2014-09-21
    • 1970-01-01
    • 2013-03-24
    • 2013-11-26
    • 2015-08-13
    • 1970-01-01
    • 2021-07-29
    • 1970-01-01
    相关资源
    最近更新 更多