在Ruby中,`@count`是实例变量还是类变量?

4
class Counter
   def self.counted_new
      @count = 0 if @count.nil?
      @count += 1
      new
   end

   def self.count
      @count
   end
end

在格式上,@count 看起来像一个实例变量,但是当我在 "irb"(即时 Ruby 解释器)中加载它并输入四条命令代码时:

Counter.counted_new
Counter.count
Counter.counted_new
Counter.count

@count 最终变成了 2!类似于类变量的行为

2个回答

9

@count始终是一个实例变量,但如果在类中声明,则可以成为类的实例变量。

在这种情况下,@count是一个类实例变量。换句话说,在类级别方法中写入@count,您正在为该类分配一个变量。

通过在实例方法中编写@count,您正在分配一个仅在该特定实例中可用的实例变量。

如果使用@@count声明变量,则会得到一个类变量。

类变量和类实例变量之间的主要区别在于类变量在继承中保留。

class Foo
  @@klass = "class level variable"
  @klass_instance = "class instance level variable"
end

class Bar < Foo
end


puts Foo.instance_variables.inspect # => [:@klass_instance]
puts Foo.class_variables.inspect  # => [:@@klass]

puts Foo.instance_variable_get(:@klass_instance)
# => "klass instance level variable"
puts Foo.class_variable_get(:@@klass)
# => "class level variable"

# The class variable is inherited, but the class instance variable is not

puts Bar.instance_variables.inspect # => []
puts Bar.class_variables.inspect  # => [:@@klass]

# The @@klass variable is shared between all classes in the downward inheritance chain
# So for example:
Foo.class_variable_set(:@@klass, "foo")
puts Bar.class_variable_get(:@@klass) # => "foo"

你可以解释得更具体一些吗?并且可以教我如何快速识别这些情况吗?因为众所周知@blah是实例变量。 - Peter Zhu
实例变量是为实例而存在的。因为你使用了Counter.count_new,所以它是在类上而不是在实例上创建的。所以@count是一个实例,但是在类中。如果你像Counter.new.count_new这样实例化一个实例,它就会在实例上而不是在类上。 - Nick Ginanto
Jesper对类变量类实例变量之间的区别进行了很好的解释。 - codingbunny
1
类实例变量和类变量之间的另一个区别是,类变量不仅可以在类方法中访问,还可以在实例方法中访问。 - Linuxios
@NickGinanto,我发现如果我声明一个名为Foo的新的Counter实例,那么Foo中的@count实例与类中的@count实例不共享同一数据字段。这是正确的吗? - Peter Zhu
@PeterZhu 如果你通过运行 Counter.new 创建一个新的 Counter 实例,那么该计数器就没有实例变量 @counter。该变量是类实例的一部分。另一方面,如果你创建一个从 Counter 继承的类 Foo,它将共享你定义的方法,但不会共享相同的 @counter 类实例变量,而是拥有自己的变量。 - Jesper

4
这样做的原因是类本身也是实例。所以你的变量表现得像一个类变量,是因为它是你的类的实例变量。
对于新手来说,这相当令人困惑,而且你正在编程的行为是否正确也是一个问题。通常情况下,类实例应该用双 @ 声明。
这里的人给出了一个很好的详细解释: 在 Ruby 中使用实例变量的类方法

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接