define_method如何使用在其外部初始化的变量


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?

因为块(做...end)是闭包,可以访问其周围范围。

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

而且,最后但并非最不重要的一点是,我可以使用define_method在这里创建类方法吗?

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

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

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

好!让我为您解释一下。你在这里看不到区别,因为Teamp1是一个Class,也是一个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

希望这有帮助!

最新更新