为什么扩展模块中的常量在使用self声明的类方法中不可用。

我认为在class << self block’中声明的方法和用self.声明的方法之间没有区别self. 前缀,但有:

 module A VAR = 'some_constant' end class B extend A class < OK B.m2 # => uninitialized constant B::VAR 

为什么A常数在m1可用而在m2不可用?

在Ruby中,常量查找与方法查找不同。 对于方法查找,调用foo始终与调用self.foo相同(假设它不是私有的)。 调用常量FOOself::FOOsingleton_class::FOO非常不同。

使用非限定常量(例如FOO )将在当前打开的模块中进行查找。 使用module Modclass Klassclass << objmodule_eval和variants打开module Mod 。 定义m1 ,这些是B ,然后是B.singleton_class 。 定义m2 ,仅打开B

 module Foo X = 42 class Bar def self.hello X end end end 

在这段代码中, Foo::Bar.hello将返回42,即使X不是Bar ,它的单例类或祖先的常量。 此外,如果稍后向Bar添加常量X ,则将返回该值。 最后,以下定义不相同:

 module Foo X = 42 end class Foo::Bar def self.hello X end end Foo::Bar.hello # => uninitialized constant Foo::Bar::X 

实际上,当定义hello时,只打开类Foo::Bar ,而在前面的示例中, FooFoo::Bar打开了。

最后一个示例,显示显式范围与inheritance的差异:

 class Base X = 42 def self.foo X end def self.bar self::X end end class Parent < Base X = :other end Parent.foo # => 42 Parent.bar # => :other 

在你的情况下, 你可能想要include你的模块,而不是extending ,不是吗?

否则,您可以使用singleton_class::VAR ,您的代码将按预期工作。

 module A VAR = 'some_constant' end class B extend A class << self def m1 puts singleton_class::VAR # not necessary here, as singleton_class is opened end end def self.m2 puts singleton_class::VAR # necessary here! end end B.m1 # => OK B.m2 # => OK