本文介绍了如何通过反射获取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?

文档状态

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

10-25 00:34