我忘记了 Ruby 中有“类实例变量”的概念。无论如何,OP的问题似乎令人费解,并且迄今为止在任何答案中都没有真正解决,除了kch的答案中的提示:这是一个范围问题。 (在编辑时添加:实际上,sris 的答案确实在最后解决了这一点,但无论如何我都会让这个答案站稳脚跟,因为我认为示例代码可能有助于理解问题。)
在 Ruby 类中,以@ 开头的变量名可以引用两个变量之一:实例变量或类实例变量,具体取决于它在类中的引用位置。这是一个相当微妙的问题。
一个例子将阐明这一点。这是一个小小的 Ruby 测试类(所有代码都在 irb 中测试过):
class T
@@class_variable = "BBQ"
@class_instance_variable_1 = "WTF"
@class_instance_variable_2 = "LOL"
def self.class_method
puts "@@class_variable == #{@@class_variable || 'nil'}"
puts "@class_instance_variable_1 == #{@class_instance_variable_1 || 'nil'}"
puts "@class_instance_variable_2 == #{@class_instance_variable_2 || 'nil'}"
puts "@instance_variable == #{@instance_variable || 'nil'}"
end
def initialize
@instance_variable = "omg"
# The following line does not assign a value to the class instance variable,
# but actually declares an instance variable withthe same name!
@class_instance_variable_1 = "wtf"
puts "@@class_variable == #{@@class_variable || 'nil'}"
# The following two lines do not refer to the class instance variables,
# but to the instance variables with the same names.
puts "@class_instance_variable_1 == #{@class_instance_variable_1 || 'nil'}"
puts "@class_instance_variable_2 == #{@class_instance_variable_2 || 'nil'}"
puts "@instance_variable == #{@instance_variable || 'nil'}"
end
def instance_method
puts "@@class_variable == #{@@class_variable || 'nil'}"
# The following two lines do not refer to the class instance variables,
# but to the instance variables with the same names.
puts "@class_instance_variable_1 == #{@class_instance_variable_1 || 'nil'}"
puts "@class_instance_variable_2 == #{@class_instance_variable_2 || 'nil'}"
puts "@instance_variable == #{@instance_variable || 'nil'}"
end
end
我根据我的想法命名变量,但事实并非总是如此:
irb> T.class_method
@@class_variable == BBQ
@class_instance_variable_1 == WTF # the value of the class instance variable
@class_instance_variable_2 == LOL # the value of the class instance variable
@instance_variable == nil # does not exist in the class scope
=> nil
irb> t = T.new
@@class_variable == BBQ
@class_instance_variable_1 == wtf # the value of the instance variable
@class_instance_variable_2 == nil # the value of the instance variable
@instance_variable == omg
=> #<T:0x000000015059f0 @instance_variable="omg", @class_instance_variable_1="wtf">
irb> t.instance_method
@@class_variable == BBQ
@class_instance_variable_1 == wtf # the value of the instance variable
@class_instance_variable_2 == nil # the value of the instance variable
@instance_variable == omg
=> nil
irb> T.class_method
@@class_variable == BBQ
@class_instance_variable_1 == WTF # the value of the class instance variable
@class_instance_variable_2 == LOL # the value of the class instance variable
@instance_variable == nil # does not exist in the class scope
=> nil
@@class_variable 和 @instance_variable 的行为总是如您所愿:前者是在类级别定义的,无论是在类方法中还是在实例方法中引用,它都会在最佳。后者只在T类的对象中获取值,所以在类方法中,它引用了一个值为nil的未知变量。
想象中命名为class_method 的类方法按预期输出@@class_variable 和两个@class_instance_variables 的值,即在类顶部初始化。但是,在实例方法initialize和instance_method中,访问的是不同变量同名,即实例变量,而不是类实例变量。
可以看到initialize方法中的赋值并没有影响到类实例变量@class_instance_variable_1,因为后面对class_method的调用输出了它的旧值"WTF"。相反,方法initialize声明了一个新的实例变量,它也命名为(误导性地)@class_instance_variable_1。分配给它的值 "wtf" 由方法 initialize 和 instance_method 输出。
示例代码中的变量@class_instance_variable_2等价于原问题中的变量@hello:它被声明并初始化为类实例变量,但是当实例方法引用该名称的变量时,它实际上看到同名的实例变量 -- 从未声明过的实例变量,因此其值为 nil。