为什么扩展模块中的常量在使用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
相同(假设它不是私有的)。 调用常量FOO
与self::FOO
或singleton_class::FOO
非常不同。
使用非限定常量(例如FOO
)将在当前打开的模块中进行查找。 使用module Mod
, class Klass
, class << obj
或module_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
,而在前面的示例中, Foo
和Foo::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