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

时间:2010-07-03 08:23:28

标签: ruby metaprogramming

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

(class << some_object; self; end).class_eval do
  define_method(:method_name) do ... method body ... end
end

(class << some_object; self; end).instance_eval do
  define_method(:method_name) do ... method body ... end
end

这两个版本的代码都定义了一个单例方法,我还没有遇到任何强迫我选择(instance_eval, define_method)组合而不是(class_eval, define_method)组合来定义单例方法的东西我想知道两者之间是否存在一些本质区别。

1 个答案:

答案 0 :(得分: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

为什么defdefine_method之间的行为存在差异? define_method是一个方法调用,因此在eval上下文中对self进行操作。 selfinstance_eval中的class_eval是相同的 - 它是接收者(o的本征类)。

def行为不同,它不会在self上运行,而是在default definee上运行。在class_eval的情况下,default defineeself相同,但对于instance_eval而言,它是self的元类。

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

它是o:

的本征类的类方法
class << o; test2; end #=> :test2