带有(class_eval,define_method)vs(instance_eval,define_method)的Ruby单例方法

dav*_*k01 17 ruby metaprogramming

ruby中的元编程非常棒,因为我经常使用它来模拟基于原型的编程,并快速编写原型解决方案来解决某些问题,以测试它们的可行性.所以我想知道以下代码之间是否存在任何本质区别:

(class << some_object; self; end).class_eval do
  define_method(:method_name) do ... method body ... end
end
Run Code Online (Sandbox Code Playgroud)

(class << some_object; self; end).instance_eval do
  define_method(:method_name) do ... method body ... end
end
Run Code Online (Sandbox Code Playgroud)

代码的两个版本定义一个单身方法,我还没有碰到任何东西,迫使我选择(instance_eval, define_method)在组合(class_eval, define_method)组合来定义一个单独的方法,我想知道是否有这两个之间有一些本质上的区别.

hor*_*guy 21

没有区别define_method.但是当你使用时会有所不同def.

o = Object.new  

# class_eval example
class << o; self; end.class_eval { def test1;  :test1; end  }
o.test1 #=> test1

# instance_eval example
class << o; self; end.instance_eval { def test2; :test2; end }
o.test2 #=> NoMethodError
Run Code Online (Sandbox Code Playgroud)

为什么def和之间的行为有所不同define_methoddefine_method是一个方法调用,因此self在eval上下文中进行操作.的self在这两个instance_evalclass_eval是相同的-它是接收机(邻的eigenclass).

然而,def行为不同,它不是在操作上self而是在操作上default define.在该情况下class_evaldefault definee是一样的self,但对于instance_eval它而不是元类self.

我们如何访问test2上面定义的方法?test2必须是在o的本征类的元类上定义的实例方法.

它是o的本征类的类方法:

class << o; test2; end #=> :test2
Run Code Online (Sandbox Code Playgroud)