我无法在方法体内修补一个类。
在方法定义中, 我试图以两种方式使用一个类:
1]创建一个实例并使用我正在使用的类中的方法的orignal定义
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)我尝试修补类的问题,因为我试图更改方法中的类。
如何在方法中实现猴子修补?
由于
答案 0 :(得分:3)
您可以使用class Clazz; blabla; end
,Clazz
和其他一些元编程实用程序/方法来执行相同操作,而不是使用Module#class_eval
重新打开Module#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