如何访问Ruby块中的实例变量?

时间:2015-06-24 20:03:49

标签: ruby

我有以下代码:

class MyXmlReader

  attr_accessor :filename, :lines

  def initialize(filename)
    @filename = filename
    @line_hash = {}
  end

  def read
    reader = Nokogiri::XML::Reader(open(@filename))
    Xml::Parser.new(reader) do
      ... do stuff
      @line_hash[var] = line           # ERROR!
    end
  end

end  

看起来该块在新范围内运行。因为我得到了:

NoMethodError: undefined method `[]' for nil:NilClass

通过创建局部变量然后将这些变量分配给read方法末尾的实例变量,可以轻松解决这个问题。但我想知道为什么在块中可以访问局部变量,而不是实例变量。

3 个答案:

答案 0 :(得分:3)

这是因为局部变量与实例变量不同,具有词法范围。 This Wikipedia article可能有帮助。

答案 1 :(得分:2)

有趣的问题不是为什么局部变量可以在块中访问(当然,块是闭包,从周围范围访问局部变量是有点重要的),而是为什么实例变量不是。实际上,因为它应该可以访问。

但是,如果该块被instance_eval编辑或instance_exec,则self的值将更改为{instance_eval的接收方1}}或instance_exec消息,实例变量总是在self中查找,因此self现在是一个不同的对象,它可能不会有{{1}实例变量。您必须查看@line_hash的实现才能找到答案。

另见How does instance_eval work and why does DHH hate it?

答案 2 :(得分:0)

我无法重现这个问题。这是一个简单的测试用例,我创建了:

          class MyReader

            def initialize
              @line_hash = {}
            end

            def read
              [1,2].each do |x|
                @line_hash[x] = '0'
              end
            end

          end  

          p MyReader.new.read