在 Ruby 中,常量查找与方法查找不同。对于方法查找,调用foo
始终与调用相同self.foo
(假设它不是私有的)。调用常量与orFOO
非常不同。self::FOO
singleton_class::FOO
使用非限定常量(例如FOO
)将在当前打开的模块中进行查找。module Mod
一个模块用, class Klass
, class << obj
, ormodule_eval
和变体打开。定义时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
其单例类或祖先的常量。此外,如果您稍后将常量添加X
到Bar
,则将返回该值。最后,以下定义不等价:
module Foo
X = 42
end
class Foo::Bar
def self.hello
X
end
end
Foo::Bar.hello # => uninitialized constant Foo::Bar::X
确实,hello
定义了 when 时,只Foo::Bar
打开了类,而在前面的例子中,同时打开了 whereFoo
和Foo::Bar
where。
最后一个例子,展示显式作用域与继承的区别:
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