使用(class_eval, define_method)与(instance_eval, define_method)实现Ruby单例方法的区别

19

在 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
请注意,执行上述操作的最佳方法是简单地使用define_singleton_method(:method_name) do ... end - Marc-André Lafortune
1个回答

22

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 运行。无论是 instance_eval 还是 class_eval 中的 self 都是相同的 - 它是接收者(即 o 的特殊类)。然而,def 表现不同,它不是基于 self 运行,而是基于default define(默认定义)。对于 class_evaldefault defineeself 相同,但对于 instance_eval,它是 self 的元类。我们如何访问上面定义的 test2 方法?test2 必须是在 o 的特殊类的元类上定义的实例方法。它是 o 的特殊类的特殊类的类方法。
class << o; test2; end #=> :test2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接