`define_method`是否在类的每个实例上运行?

时间:2019-05-14 21:02:03

标签: ruby performance metaprogramming

当我的班级动态创建一堆便利方法时,像这样:

class MyClass < ActiveRecord::Base
  ...
  %w(foo bar baz).freeze.each do |part_one|
    %w(alpha beta gamma).freeze.each do |part_two|
      define_method "#{part_one}_#{part_two}" do
        lookup_stuff(part_one, part_two)
      end
    end
  end
  ...
end

迭代和方法创建是否针对该类的每个实例进行,或者仅在首次解析该类并创建该类的模型对象时才进行一次?

我有一种预感,它只会发生一次,但是我在文档中找不到任何可以证实这一点的东西。

2 个答案:

答案 0 :(得分:0)

通常,仅当属于类定义的一部分时,才对代码进行一次评估,例如:

class Example
  # Code here is executed immediately in the order the statements appear
  %w[ foo bar baz ].each do |...|
  end

  def example
    # Code here is only run if this method is executed, and only when
    # the method is executed.
  end
end

您可以使用“ printf调试”进行查找:

class Example
  puts "Am I being run once or a whole bunch of times?"

  %w[ foo bar baz ].each do |...|
  end
end

现在将在此处清空您可以使用的某些诊断输出。

例外情况是在Ruby on Rails自动加载程序开发环境中,其中app/中的内容将针对每个请求而不是针对每个进程进行一次加载。

答案 1 :(得分:0)

Ruby中的方法总是在模块(或类,是一种特定的模块)上定义的,而不是在实例上定义的。虽然显然可以在实例上定义一种方法,例如

Matcher m = Pattern.compile("\\([^()-]*-[^()]*\\)").matcher(s); return !m.find();

这实际上是将方法放在所谓的class Foo; end foo = Foo.new def foo.quux puts "QUUX" end foo.quux # => QUUX bar = Foo.new bar.quux # => QUUX 的单例类中,该类是Foo派生的。在Ruby中的实例上没有定义任何方法。当一个方法调用时,它会在继承链中查找。

您的foo将在执行时填充define_method的方法;从此以后,self.class或其后代的任何实例都可以访问它们。