Ruby 在运行时将一行代码注入现有方法
在运行时,我想在Ruby v2.0之前的-Ruby 在运行时将一行代码注入现有方法,ruby,Ruby,在运行时,我想在Ruby v2.0之前的-中注入一行代码,在对原始的a#some_方法进行别名处理后,重新定义a#some_方法 class A def some_method(a, b, c) puts a puts b puts c end end A.prepend M 但是,更好的方法是在模块中定义新方法A#some_方法,然后将该模块定义到类Aprepend在Ruby v2.0中首次亮相 module M def some_method(a,b,
中注入一行代码,在对原始的a#some_方法
进行别名处理后,重新定义a#some_方法
class A
def some_method(a, b, c)
puts a
puts b
puts c
end
end
A.prepend M
但是,更好的方法是在模块中定义新方法A#some_方法
,然后将该模块定义到类A
prepend
在Ruby v2.0中首次亮相
module M
def some_method(a,b,c)
puts "a=#{a}, b=#{b}, c=#{c}"
super
end
end
A.prepend M
A.prepend M
给出了M
优先于A
的方法
A.prepend M
A.ancestors
#=> [M, A, Object, Kernel, BasicObject]
说明了这种情况,并解释了super
在方法M#some_方法中的作用
class A
def some_method(a, b, c)
puts a
puts b
puts c
end
end
A.prepend M
我之所以需要它,是因为我可以使用Ruby Tracepoint类来提取有关方法签名的一些运行时信息
特别是b=1和d:1中的默认参数值
TracePoint
允许您在不修补方法的情况下获取信息。您只需设置一个:调用钩子,然后调用该方法:
A.prepend M
TracePoint.trace(:call) do |tp|
tp.parameters.each do |type, name|
value = tp.binding.local_variable_get(name)
puts format('%8s: %s = %s', type, name, value.inspect)
end
end
A.new.some_method(123)
输出:(省略方法的输出)
req:a=123
A.prepend M
选项:b=1
rest:c=[]
关键字:d=1
keyrest:e={}
您是否能够在模块中定义这些方法?如果是这样,那么您也可以在类中简单地重新定义它们,并且可以对它们调用super,这样您就可以:(i)添加注入,然后保留方法在模型中要执行的功能。或者,你可以重命名这些方法,然后添加注入吗?再次感谢Stefan(连续两天),这正是我所需要的。我刚刚添加了下一步,除非tp.self.is_a?(a)
,以消除噪音。感谢Cary提供的信息,不幸的是,这对我的用例不起作用,因为我无法访问代码进行更改,其想法是反向工程来自GEMs和其他我可能无法轻松访问的代码的签名。
A.prepend M