为什么这个变量在结构中消失了?

时间:2012-03-24 23:19:37

标签: ruby struct

也许我对结构没有足够的了解并盲目地使用它们,但下面的结果对我来说似乎是不合理的。

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

有人可以解释一下这是怎么回事吗?

感谢。

1 个答案:

答案 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}"来验证。)