也许我对结构没有足够的了解并盲目地使用它们,但下面的结果对我来说似乎是不合理的。
class VarTest < Struct.new(:email)
def perform
puts "Start: #{email}"
if email == "nothing"
email = "bad email"
end
puts "End: #{email}"
end
end
VarTest.new("test@example.com").perform
意外输出:
Start: test@example.com
End:
如果我将代码更改为:
class VarTest < Struct.new(:email)
def perform
e = email
puts "Start: #{e}"
if e == "nothing"
e = "bad email"
end
puts "End: #{e}"
end
end
VarTest.new("test@example.com").perform
我们得到预期的输出:
Start: test@example.com
End: test@example.com
有人可以解释一下这是怎么回事吗?
感谢。
答案 0 :(得分:4)
如果您将email = "bad email"
替换为self.email = "bad email"
,它将按预期工作。使用setter时总是如此。
原因很简单:当Ruby遇到一个裸字时,它会尝试将其解析为本地var。如果没有,它将尝试按该名称调用方法。在课堂内部,自我是隐含的接收者,所以读者才能工作。对于作家来说,这是一个问题。如果您编写类似foo = "bar"
的内容,Ruby将创建一个新的局部变量,因此您需要使接收器显式化。
这种情况有点棘手:if email == "nothing"
使用getter。但是,解析器仍会看到email = "bad email"
,并且局部变量email
将设置为nil
。当解析器将裸字视为赋值的LHS时,总会发生这种情况。这个本地nil
值似乎使email
的值消失(您可以通过仅将最后puts
更改为puts "End: #{self.email}"
来验证。)