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?
答案 0 :(得分:4)
因为块(do ... end)是闭包并且可以访问它们 周边范围。
您使用了class_eval
的块,因此它可以访问其周围环境,这是方法add
的范围。现在,您使用define_method
的另一个块,该块也可以通过add
的块访问方法范围class_eval
。match
局部变量已被在方法add
的范围内创建。因此块可以访问变量。
最后但并非最不重要的是,我可以使用define_method创建类方法吗?
不,你不能。define_method
在接收器中定义实例方法。self.class
是Temp1
。现在在Temp1.class_eval do..end
下,您正在使用方法Temp1
定义类define_method
的实例方法。define_method
是所有类的私有类方法,其中祖先链Object
上课。
class C;end
C.private_methods.grep(/define_/)
# => [:define_method]
另外,我在使用class_eval或instance_eval之间没有区别,看起来它做同样的事情。
好!让我为你解释一下。您无法在此处看到差异,因为Teamp1
是Class
,也是Class
的实例。在致电class_eval
和instance_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
希望这有帮助!