如何在子类中的方法之前和之后运行代码?

Kri*_*ris 6 ruby metaprogramming

我的第一个想法是这样的事情:

class AbstractBuilder
  attr_reader :time_taken

  def build_with_timer
    started_at = Time.now
    build
    @time_taken = Time.now - started_at
  end

  def build
    raise 'Implement this method in a subclass' 
  end
end

class MyBuilder < AbstractBuilder
  def build
    sleep(5)
  end
end

builder = MyBuilder.new.build_with_timer
puts builder.time_taken
Run Code Online (Sandbox Code Playgroud)

我怀疑有一种更好的方法可以提供更好的灵活性,例如理想情况下我想在MyBuilder的实例上调用'build'而不是'build_with_timer'并且总是记录执行时间.

我确实考虑过使用初始化的alias_method,甚至使用模块mixin而不是类继承,它会覆盖在中间调用super的构建方法(不确定是否可行).在我走下兔子洞之前,我想我会看看是否有既定的做法.

Mla*_*vić 3

我会玩alias_method

module Timeable
  def time_methods *meths
    meths.each do |meth|
      alias_method "old_#{meth}", meth

      define_method meth do |*args|
        started_at = Time.now
        res = send "old_#{meth}", *args
        puts "Execution took %f seconds" % (Time.now - started_at)
        res
      end
    end
  end

end

class Foo
  def bar str
    puts str
  end
end

Foo.extend Timeable
Foo.time_methods :bar
Foo.new.bar('asd')
#=>asd
#=>Execution took 0.000050 seconds
Run Code Online (Sandbox Code Playgroud)