问题描述
我试图将Matz和Flanagan的"Ruby编程语言"元编程章节带入我的脑海,但是我无法理解我梦the以求的以下代码片段的输出:
I was trying to get Matz and Flanagan's "Ruby Programming Language" metaprogramming chapter into my head, However I couldn't understand the output from the following code snippet that I dreamed up:
p Module.constants.length # => 88
$snapshot1 = Module.constants
class A
NAME=:abc
$snapshot2 = Module.constants
p $snapshot2.length # => 90
p $snapshot2 - $snapshot1 # => ["A", "NAME"]
end
p Module.constants.length # => 89
p Module.constants - $snapshot1 # => ["A"]
p A.constants # => ["NAME"]
这本书指出,类方法constants
返回该类的常量列表(如您在A.constants
的输出中看到的那样).当我遇到上述奇怪的行为时,我试图获取为Module类定义的常量列表.
The book states that the class method constants
returns the list of constants for the class (as you can see in the output for A.constants
).I was trying to get the list of constants defined for the Module class when I came across the above strange behavior.
A
的常量显示在Module.constants中.如何获取Module类定义的常量列表?
A
's constants show up in Module.constants. How do I get the list of constants defined by the Module class?
文档状态
由于A
从Module.constants
继承了其实现,因此它在基本类型和派生类型中的行为如何不同?
Since A
inherits its implementation from Module.constants
, how does it behave differently in the base and derived types?
p A.class # => Class
p A.class.ancestors # => [Class, Module, Object, Kernel]
注意:如果您使用的是Ruby 1.9,constants
将返回符号数组,而不是字符串.
Note: If you're using Ruby 1.9, constants
would return an array of symbols instead of strings.
推荐答案
好问题!
您的困惑是由于以下事实:类方法Module.constants
为Module
隐藏了实例方法Module#constants
.
Your confusion is due to the fact that the class method Module.constants
hides the instance method Module#constants
for Module
.
在Ruby 1.9中,已通过添加可选参数解决了该问题:
In Ruby 1.9, this has been addressed by adding an optional parameter:
# No argument: same class method as in 1.8:
Module.constants # ==> All constants
# One argument: uses the instance method:
Module.constants(true) # ==> Constants of Module (and included modules)
Module.constants(false) # ==> Constants of Module (only).
在上面的示例中,A.constants
调用Module#constants
(实例方法),而Module.constants
调用Module.constants
.
In your example above, A.constants
calls Module#constants
(the instance method), while Module.constants
calls, well, Module.constants
.
因此在Ruby 1.9中,您想调用Module.constants(true)
.
In Ruby 1.9, you thus want to call Module.constants(true)
.
在Ruby 1.8中,可以在Module
上调用实例方法#constants
.您需要获取实例方法并将其绑定为类方法(使用其他名称):
In Ruby 1.8, it is possible to call the instance method #constants
on Module
. You need to get the instance method and bind it as a class method (using a different name):
class << Module
define_method :constants_of_module, Module.instance_method(:constants)
end
# Now use this new class method:
class Module
COOL = 42
end
Module.constants.include?("COOL") # ==> false, as you mention
Module.constants_of_module # ==> ["COOL"], the result you want
我希望能够将backports
gem的1.9功能完全回迁到1.8,但是我想不出一种方法来在Ruby 1.8中仅获取Module的常量,但不包括继承的常量.
I wish I was able to backport the 1.9 functionality completely to 1.8 for my backports
gem, but I can't think of a way to get only the constants of a Module, excluding the inherited ones, in Ruby 1.8.
编辑:只是更改了官方文档以正确反映这一点...
Edit: Just changed the official documentation to correctly reflect this...
这篇关于如何通过反射获取Ruby的Module类定义的常量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!