如何全局前置Kernel模块的rand方法?期望三类调用均生效
解决方案
要让Kernel.rand、全局rand以及所有对象实例调用的rand都触发自定义逻辑,得同时处理Kernel的实例方法和单例方法——因为rand在Ruby里是双重身份:既是所有对象都能调用的Kernel实例方法,也是可直接通过Kernel.rand/全局rand调用的单例方法。
方法一:用模块前置覆盖两类方法
# 定义包含自定义逻辑的模块 RandHook = Module.new do def rand(*args) p "do something" super(*args) end end # 覆盖Kernel的实例方法(影响所有对象的rand调用,比如Object.new.send(:rand)) Kernel.prepend(RandHook) # 覆盖Kernel的单例方法(影响Kernel.rand和全局rand调用) Kernel.singleton_class.prepend(RandHook)
测试验证:
Kernel.rand # 打印"do something"并返回随机数 rand # 打印"do something"并返回随机数 Object.new.send(:rand) # 打印"do something"并返回随机数
方法二:直接重定义方法(更简洁)
如果不需要保留方法的动态查找逻辑(比如确定不会有其他模块修改rand),可以直接保存原方法后重定义:
# 重定义实例方法 original_instance_rand = Kernel.instance_method(:rand) Kernel.define_method(:rand) do |*args| p "do something" original_instance_rand.bind(self).call(*args) end # 重定义单例方法 original_singleton_rand = Kernel.method(:rand) Kernel.define_singleton_method(:rand) do |*args| p "do something" original_singleton_rand.call(*args) end
内容的提问来源于stack exchange,提问作者vetements
相关产品推荐
相关产品推荐

