为什么来自扩展模块的常量在用 self. 声明的类方法中不可用? [英] Why are constants from extended module not available in class methods declared with self.?
问题描述
我认为在 类中声明的方法之间没有区别 <<self
块和那些用 self.
前缀声明的块,但有:
I thought there were no differences between methods declared within a class << self
block and those declared with a self.
prefix, but there are:
module A
VAR = 'some_constant'
end
class B
extend A
class << self
def m1
puts VAR
end
end
def self.m2
puts VAR
end
end
B.m1 # => OK
B.m2 # => uninitialized constant B::VAR
为什么A
的常量在m1
中可用,而在m2
中不可用?
Why are constants of A
available in m1
but not in m2
?
推荐答案
在 Ruby 中,常量查找与方法查找不同.对于方法查找,调用 foo
始终与调用 self.foo
相同(假设它不是私有的).调用常量FOO
与self::FOO
或singleton_class::FOO
非常不同.
In Ruby, constant lookup is not the same as method lookup. For method lookup, calling foo
is always the same as calling self.foo
(assuming it isn't private). Calling a constant FOO
is very different from self::FOO
or singleton_class::FOO
.
使用非限定常量(例如 FOO
)将在当前打开的模块中进行查找.一个模块用module Mod
、class Klass
、class <<<;obj
或 module_eval
和变体.定义m1
时,它们是B
,然后是B.singleton_class
.定义m2
时,只打开B
.
Using an unqualified constant (e.g. FOO
) will do a lookup in the currently opened modules. A module is opened with module Mod
, class Klass
, class << obj
, or module_eval
and variants. When defining m1
, these are B
, and then B.singleton_class
. When defining m2
, only B
is opened.
module Foo
X = 42
class Bar
def self.hello
X
end
end
end
在这段代码中,Foo::Bar.hello
将返回 42,即使 X
不是 Bar
的常量,它的单例阶级或祖先.此外,如果您稍后将常量 X
添加到 Bar
,则将返回该值.最后,以下定义是不等价的:
In this code, Foo::Bar.hello
will return 42, even though X
is not a constant of Bar
, its singleton class or ancestor. Also, if you later add a constant X
to Bar
, then that value will be returned. Finally, the following definition is not equivalent:
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
打开的地方.
Indeed, when hello
is defined, only the class Foo::Bar
is opened, while in the previous example, both Foo
and Foo::Bar
where opened.
最后一个例子,显示显式作用域与继承的区别:
A last example, to show the difference an explicit scope can have with 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
它,不是吗?
In your case, you probably want to include
your module, instead of extending
it, no?
否则,您可以使用 singleton_class::VAR
,您的代码将按预期工作.
Otherwise, you could use singleton_class::VAR
, your code will work as you expect it.
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
这篇关于为什么来自扩展模块的常量在用 self. 声明的类方法中不可用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!