我正在做一些(太)花哨的元编程,我很难理解为什么在以下两种情况下范围不同:

案例 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/

10-11 22:37
查看更多