2
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 =“哈哈”,方法会以某种方式打印“哈哈”。有人可以解释一下吗?

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

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

4

1 回答 1

5

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

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

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

不,你不能。在接收器中定义一个实例方法。是。现在,您正在使用方法定义类的实例方法。是所有类的私有类方法,其中存在祖先链类。define_method self.classTemp1Temp1.class_eval do..endTemp1define_methoddefine_methodObject

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

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

好的!让我为你解释一下。您看不到这里的区别,Teamp1aClass和 a 的实例也是如此Class。在 callclass_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

希望这可以帮助!

于 2013-11-02T14:52:39.443 回答