【问题标题】:How define_method uses variables initialised outside of itdefine_method 如何使用在其外部初始化的变量
【发布时间】:2013-11-02 14:24:13
【问题描述】:
class Temp1
  def add(s)
    match = 'test'
    self.class.class_eval do
       define_method(s) do
         puts match
       end
    end
    #match ='haha'
  end
end

在我看来,'match' 是一个局部变量,所以我不明白它如何从另一种方法中看到它,另外,如果取消注释 #match ='haha',方法会以某种方式打印'haha'。谁能解释一下?

另外,我没有看到使用 class_eval 或 instance_eval 之间的区别,似乎它做同样的事情。

最后但同样重要的是,我可以在这里使用define_method 创建类方法吗?所以我可以把它称为 Temp1.something 而不是 Temp1.new.something?

【问题讨论】:

    标签: ruby-on-rails ruby metaprogramming


    【解决方案1】:

    因为块 (do...end) 是闭包并且可以访问它们的 周围的范围。

    你使用了class_eval的block,所以它可以访问它的周围环境,这是add方法的作用域。现在您使用另一个带有define_method 的块,它也可以访问方法add 的范围,通过带有class_eval 的块。match 局部变量已在方法@ 的范围内创建987654330@。所以块可以访问变量。

    最后但同样重要的是,我可以在这里使用 define_method 创建类方法吗?

    不,你不能。define_method 在接收器中定义一个实例方法self.classTemp1。现在在Temp1.class_eval do..end下,定义了Temp1类的实例方法,define_method.define_method方法是所有类的私有类方法,其中祖先链Object类存在。

    class C;end
    C.private_methods.grep(/define_/)
    # => [:define_method]
    

    另外,我看不出使用class_evalinstance_eval 之间的区别,似乎它做同样的事情。

    好的!让我为你解释一下。您在这里看不到区别,因为Teamp1Class,也是Class 的一个实例。在class_evalinstance_eval 的两个调用中,self 被设置为Teamp1,按照文档中各自的定义。

    class C
      def self.bar;11;end
      def baz;12;end
    end
    
    C.is_a? Class # => true
    C.instance_of? Class # => true
    
    C.class_eval{ bar } # => 11
    C.instance_eval{ bar } # => 11
    

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-13
      • 1970-01-01
      • 2012-07-04
      相关资源
      最近更新 更多