我们假设我们有这个Ruby类:
class MyClass class << self MC_CONST = 30 end end
然后,让我们实例化MyClass
并向对象的元类添加另一个常量:
m = MyClass.new class << m OBJ_MC_CONST = 50 end
对象单例常量没有问题:
m.singleton_class::OBJ_MC_CONST # => 50 <-- [OK] m.singleton_class.constants.include? :OBJ_MC_CONST # => true <- [OK]
但不完全是我对类单例常量的期望:
MyClass.singleton_class::MC_CONST # => 30 <-- [OK] MyClass.singleton_class.const_get :MC_CONST # => 30 <-- [OK] MyClass.singleton_class.constants.include? :MC_CONST # => false <-- [Why???]
为什么在.constants
类的元MyClass
类上由方法返回的数组不包含:MC_CONST?我在这里错过了什么?
谢谢.
编辑1:毕竟这似乎是MRI 2.x中的一个错误.我已经向Ruby核心团队提出了一个新问题:https://bugs.ruby-lang.org/issues/9413来解决这个问题.
编辑2:这个错误显然已在https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/44628/diff/中修复
我已经对这个问题进行了一些探讨,我认为这是由于MRI的错误/不一致/特异性引起的.
在MRI 2.1.0上,这段代码:
class MyClass class << self MC_CONST = 30 end end p MyClass.singleton_class.const_defined? :ABBA_CONST, false p MyClass.singleton_class.const_defined? :MC_CONST, false p MyClass.singleton_class.constants(false)
产量
false true []
所以MC_CONST
定义了常量,但是它不能作为类的局部常量(我将错误传递给各种方法以禁用常量分辨率并将其保持在该类的本地),这应该是确实的.如果我们查看Module#常量的文档,它会说:
返回mod中可访问的常量名称数组.除非将all参数设置为false,否则这包括任何包含的模块中的常量名称(示例在部分的开头).
另见Module :: const_defined?.
所以它告诉我们检查const_defined?
以更好地理解行为constants
,但这两种方法给出了不同的结果!
此外,在其他Ruby实现上,此代码按预期工作.
在JRuby 1.7.9上,它产生:
false true [:MC_CONST]
在Rubinius 2.2.1上,它产生:
false true [:MC_CONST]
这是预期的行为:)