如何通过反射获取Ruby的Module类定义的常量? [英] How do I get constants defined by Ruby's Module class via reflection?

查看:84
本文介绍了如何通过反射获取Ruby的Module类定义的常量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图将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?

文档状态

Module.constants返回系统中定义的所有常量.包括所有类和方法的名称

Module.constants returns all constants defined in the system. including names of all classes and methods

由于AModule.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.constantsModule隐藏了实例方法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类定义的常量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆