Ruby中类调用is_a?Module返回true的问题及递归函数需求
问题说明
在Ruby代码中,定义嵌套模块与类后,执行puts A::B::C.is_a? Module返回true,但C是类,用户对此存在困惑。同时用户想要实现一个能根据类/模块实例执行对应操作的递归函数,当前编写的函数存在问题。
示例代码
module A module B class C puts A::B.is_a? Class puts A::B.is_a? Module puts A::B::C.is_a? Class puts A::B::C.is_a? Module end end end
输出结果
false true true true
当前递归函数代码
def recursive(rootModule) sampleList = [] rootModule.constants.map do |c| nextLayer = rootModule.const_get(c) if nextLayer.is_a? Module return recursive(nextLayer) elsif nextLayer.is_a? Class return sampleList << "alpha" end end end
问题解析与解决方案
为什么类会被判定为模块?
Ruby的类体系里,Class是Module的子类,所有类对象同时属于模块的实例范畴,因此is_a? Module检查类时会返回true。如果需要严格区分类和模块,改用instance_of?方法:
puts A::B::C.instance_of? Class # => true puts A::B::C.instance_of? Module # => false
修正递归函数
原函数存在两个核心问题:
- 使用
return导致遍历到第一个匹配项就直接终止,无法处理所有常量 sampleList每次递归都会重新初始化,无法累积结果
修正后的递归函数:
def recursive(root_module, sample_list = []) root_module.constants.each do |c| next_layer = root_module.const_get(c) if next_layer.is_a?(Class) sample_list << "alpha" elsif next_layer.is_a?(Module) recursive(next_layer, sample_list) end end sample_list end
关键调整点:
- 将
sample_list作为参数传递,实现跨递归调用的结果累积 - 用
each替代map(无需返回映射数组),移除不必要的return,确保遍历所有常量 - 优先判断
Class(因类是模块子类,先判断类可避免被模块分支捕获),也可结合instance_of?做严格区分
内容的提问来源于stack exchange,提问作者Jhots
相关产品推荐
相关产品推荐

