我正在做一些(太)花哨的元编程,我很难理解为什么在以下两种情况下范围不同:
案例 1:
class TesterA
def the_method
puts "I'm an instance_method!"
end
def self.the_method
puts "I'm a class_method!"
end
def self.define_my_methods *method_names
method_names.each do |name|
define_method("method_#{name}") do
the_method
end
end
end
define_my_methods :a, :b, :c
end
t = TesterA.new
t.method_a #=> I'm an instance_method!
t.method_b #=> I'm an instance_method!
t.method_c #=> I'm an instance_method!
案例 2
class TesterB
def the_method
puts "I'm an instance_method!"
end
def self.the_method
puts "I'm a class_method!"
end
def self.define_the_method attr
define_method("method_#{attr}") do
begin
yield
rescue
raise $!, "method_#{attr} was called: #$!", $@
end
end
end
def self.define_my_methods *method_names
method_names.each do |name|
define_the_method(name) do
the_method
end
end
end
define_my_methods :a, :b, :c
end
t = TesterB.new
t.method_a #=> I'm a class_method!
t.method_b #=> I'm a class_method!
t.method_c #=> I'm a class_method!
我在第二个例子中介绍了一种“辅助方法”
define_the_method
,我用它来定义方法而不是 define_method
它自己。原因是,我想将动态方法的名称附加到这些方法中可能发生的任何异常消息中。然而问题是,内容(当使用后一种情况时)似乎是在类范围内评估的。为什么会这样,我怎样才能让它在实例范围内得到评估?
最佳答案
这是因为使用 proc
定义的 define_method
将通过使用 instance_eval
调用。
在第一个示例中,它是:
do
the_method
end
第二:
do
begin
yield
rescue
raise $!, "method_#{attr} was called: #$!", $@
end
end
但是
yield
将从定义它的位置开始具有父作用域。这是我的建议:
def self.define_the_method attr, &block
define_method("method_#{attr}") do
begin
instance_eval(&block)
rescue
raise $!, "method_#{attr} was called: #$!", $@
end
end
end
关于ruby - 为什么我的define_method 内容在类范围内被评估?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45958297/