我有一个代码:
class A
attr_accessor :somevar
def a
somevar = 'something'
puts @somevar
end
def b
send :somevar=, 'something'
puts @somevar
end
end
A.new.a #=> nil
A.new.b #=> 'something'
为什么会有区别?为什么我不能通过编写器分配实例变量?但是为什么已经创建了局部变量而不是方法(setter)呢?
答案 0 :(得分:7)
attr_accessor :somevar
引用实例变量@somevar
。实例变量必须以@
符号开头。在方法中没有@
符号的所有其他变量(如'somevar')只是该方法或范围的局部变量,而不是对象的实例变量。
因此,将方法“a”中的第一行更改为
@somevar = 'something'
将得出您期望的答案。
相关说明:您不必在Ruby中声明实例变量,只需使用@somevar
类型表示法创建它们。 attr_accessor
方法为该实例变量创建setter和getter。
Ruby中的方法附加到对象,因此为了让A类调用自己的somevar setter方法,您需要编写self.somevar = 'something'
,否则Ruby解析器会认为您只是创建了一个局部变量。 / p>
这可能令人困惑,因为您可以通过以下方式从a
调用方法b
:
def b
send :somevar=,'something'
puts @somevar
a # would invoke its own method 'a'
end
但是setter方法somevar=
与创建具有相同表示法的局部变量不明确:
somevar='something' # Ruby assumes you want to create a local variable
所以要调用somevar setter方法,你需要明确地说你在自己上调用方法:
self.somevar = 'something'
当您调用send :somevar=,'something'
时,您也调用了somevar实例方法。
答案 1 :(得分:1)
这是因为方法a正在创建一个名为somevar的局部变量。这只是Ruby的一个小怪癖。您可以通过self.somevar = 'something'
或@somevar = 'something'
来解决此问题。