Ruby 2.7+如何编程识别super调用链中当前方法所属混入模块
适用版本
Ruby 2.7+
问题描述
多个通过mixin机制混入类的模块如果定义了同名方法,调用时这些方法会通过super关键字沿方法链依次触发,所有混入模块中的同名方法都会执行。需要通过编程方式(非硬编码)识别当前运行的方法所属的混入来源模块,替换示例代码中的占位输出。
原示例代码如下:
module A def initialize(*args, **kwargs) puts("something magic") end end module B def initialize(*args, **kwargs) puts("something magic") end end class C include A include B def initialize(*args, **kwargs) puts("actual #{self.class.name} initialize") super end end
运行上述代码会输出三行内容,需要找到类似self.class.name、可对应到具体模块的属性,识别当前运行的initialize方法由哪个模块提供。
实现方案
在方法内部通过method(__method__).owner即可获取当前执行方法的原始定义所属模块/类,调用该对象的name方法就能拿到对应的模块名。
修改后的可运行代码:
module A def initialize(*args, **kwargs) puts("initialize from #{method(__method__).owner.name}") super end end module B def initialize(*args, **kwargs) puts("initialize from #{method(__method__).owner.name}") super end end class C include A include B def initialize(*args, **kwargs) puts("actual #{self.class.name} initialize") super end end C.new
运行输出结果:
actual C initialize initialize from B initialize from A
补充说明:Ruby模块混入的方法调用顺序实际是确定的,遵循后混入优先规则,最后执行include的模块会排在方法查找链更靠前的位置,会更早被触发。
内容的提问来源于stack exchange,提问作者RoUS
相关产品推荐
相关产品推荐

