3

我无法在方法体内修补类。

在方法定义中,我尝试以两种方式使用类:

1]创建一个实例并在我正在使用的类中使用方法的原始定义

2]猴子补丁(pverride)类中的方法,现在使用具有新方法定义的实例。

基本上我会在我的程序中使用上述两个类的实例。

挑战是我要覆盖的方法在初始化期间被调用,所以我必须在创建类的实例之前覆盖它。

这是一个小模型:

class A

  def initialize
   do_something
  end

  def do something
     #implementation
  end

end

现在,我想在同一个方法中使用 A 两次,但一次使用修改版本的 do_something 这就是我尝试这样做的方式:

def my_method

  orig_instance = A.new

  #patch the class
  Class A          # ERROR: CLASS DEF IN METHOD BODY
   class << self
     alias_method :old_do_something, :do_something

     def self.do_something
        # new implementation
     end
  end

  new_instance = A.new

  #restore method
   class << self
     alias_method :do_something,:old_do_something

     def self.do_something
        # new implementation
     end
  end        



end # end of method

我得到 (ERROR: CLASS DEF IN METHOD BODY) 我试图对类进行修补,因为我试图在方法内更改类。

如何在方法中实现猴子修补类?

谢谢

4

1 回答 1

3

您可以使用,和其他一些元编程实用程序/方法来执行相同的技巧,而不是使用class Clazz; blabla; end重新打开和猴子修补它。而且由于这些方法接受的块不会创建新的绑定范围,因此在元编程实践中更方便。ClazzModule#class_evalModule#instance_eval

def my_method
  puts ">> creating orig_instance"
  orig_instance = A.new

  puts ">> dump orig_instance"
  orig_instance.do_something

  new_do_something = lambda do
    puts "Modified A#do_something"
  end

  # monkey patch class A so that the modified version of do_something get called
  # during initialization of new_instance
  A.class_eval do
    alias_method :old_do_something, :do_something
    define_method :do_something, new_do_something
  end

  puts ">> creating new_instance"
  new_instance = A.new

  puts ">> dump before do_something gets restored"
  new_instance.do_something
  orig_instance.do_something

  # add singleton method for the special instance
  # so that the instance always calls the modified do_something
  new_instance_singleton = class << new_instance; self end
  new_instance_singleton.send :define_method, :do_something, new_do_something

  # restore the modified do_something
  # so that orig_instance and all other instances (except new_instance) have the original definition
  A.class_eval do
    alias_method :do_something, :old_do_something
  end
  puts ">> dump for final result"
  new_instance.do_something
  orig_instance.do_something
end

以下是my_method调用的输出:

>> creating orig_instance
Original A#do_something
>> dump orig_instance
Original A#do_something
>> creating new_instance
Modified A#do_something
>> dump before do_something gets restored
Modified A#do_something
Modified A#do_something
>> dump for final result
Modified A#do_something
Original A#do_something
于 2013-07-16T01:54:57.957 回答