Ruby 求解 define_method 中变量的作用域

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

代码如下

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]



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

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

匿名 #2 2012年04月24日

既不懂你的疑惑也不懂 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

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

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