Ruby 求解 define_method 中变量的作用域

niedhui · 2012年04月24日 · 最后由 zgm 回复于 2012年04月24日 · 2645 次阅读

代码如下

module M
  def define_keys(*keys)
    define_method :hello do 
       keys += [:hello,:bye]
    end
  end
end

class A
  extend M
  define_keys :nihao
end

a = A.new
p a.hello
#output [:nihao, :hello, :bye]
p a.hello
#output [:nihao, :hello, :bye, :hello, :bye]
p a.hello
#output  [:nihao, :hello, :bye, :hello, :bye, :hello, :bye]
b = A.new
p b.hello
#output  [:nihao, :hello, :bye, :hello, :bye, :hello, :bye, :hello, :bye]



一开始以为每次的结果都应该一样的,不太懂啊

共收到 5 条回复

这个不奇怪啊,你弄了一个闭包。

既不懂你的疑惑也不懂B是从哪来的..

define_method :hello do keys += [:hello,:bye] end

这个代码块创建了一个proc对象并创建了一个define_keys方法的binding,关联到 这个proc对象,也就是闭包了,不知道咋描述。

而这个keys, 可以认为是这个proc对象,有个引用,初始为keys, 每次调用a.hello, 都会调用 这个proc对象,并更新那个keys的引用,所以会出现这样的结果。

就跟如下的代码,效果一样.

module M
  def define_keys(*keys)
    local_keys = keys
    define_method :hello do 
        local_keys += [:hello,:bye]
    end
  end
end


#1楼 @hisea #3楼 @wx1452 懂了,谢谢,proc一直在用,忽略了闭包,binding这一说了.

#4楼 @niedhui

class C
    def self.say(*args)
         Proc.new{|c|  args << c }
    end
    p = say('niedhui')
    p p.call('h')
    p p.call('e')
    p p.call('l')
    p p.call('l')
    p p.call('o')
end

这个代码和你的差不多意思。会更好理解点吧。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册