在Ruby中,<ClassName>.constants
对于检查类非常有用:
> Numeric.constants(false)
=> [:KILOBYTE, :MEGABYTE, :GIGABYTE, :TERABYTE, :PETABYTE, :EXABYTE]
> Object.constants(false)
=> [:Object, :Module, ...]
这在Module
:
> Object.method(:constants)
=> #<Method: Class(Module)#constants>
我想添加另一种方法来打印包含所有常量及其值的哈希。这是迄今为止的结果:
def Module.constants_hash(inherit=true)
self.constants(inherit).inject({}) do |hash, constant|
hash[constant] = self::const_get(constant)
hash
end
end
这适用于Module
(虽然它没有常量,因此结果只是一个空哈希),但它没有被继承:
> Object.constants_hash(false)
NoMethodError: undefined method `constants_hash' for Object:Class
from (pry):117:in `<main>'
我当然可以将代码中的类名更改为例如Object
使调用工作,但是是否可以使所有依赖模块继承新方法?换句话说,是否可以在运行时添加方法,然后由require
修改后的类继承?
我不会过载原始Module.constants
,以避免更改API。
答案 0 :(得分:4)
Object
是Class
类型的实例。 Class
类继承自Module
。要使Object.constants_hash
生效,您需要定义Class
或Module
类的实例方法:
class Module
def constants_hash(inherit=true)
self.constants(inherit).inject({}) do |hash, constant|
hash[constant] = self::const_get(constant)
hash
end
end
end
在您的代码中,您只需将constants_hash
添加到Module
实例(类型Class
)的单件类中,这就是您无法获得的原因预期的结果。
答案 1 :(得分:0)
您可以通过在模块中声明此方法,然后根据需要将其混合到每个上下文中来获得更好的运气:
module ConstantsHash
def constants_hash(inherit = true)
Hash[
self.constants(inherit).collect do |constant|
[ constant, const_get(constant) ]
end
]
end
end
Module.extend(ConstantsHash)
Object.extend(ConstantsHash)
puts Object.constants_hash.inspect
请注意,使用Hash[]
代替inject({ })
似乎在这种情况下效果更好。