Ruby Class Singleton常量存储在哪里?

dem*_*isx 7 ruby singleton constants

我们假设我们有这个Ruby类:

class MyClass
  class << self
    MC_CONST = 30
  end
end 
Run Code Online (Sandbox Code Playgroud)

然后,让我们实例化MyClass并向对象的元类添加另一个常量:

m = MyClass.new
class << m
  OBJ_MC_CONST = 50
end
Run Code Online (Sandbox Code Playgroud)

对象单例常量没有问题:

m.singleton_class::OBJ_MC_CONST # => 50 <-- [OK]
m.singleton_class.constants.include? :OBJ_MC_CONST # => true <- [OK]
Run Code Online (Sandbox Code Playgroud)

但不完全是我对类单例常量的期望:

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???]
Run Code Online (Sandbox Code Playgroud)

为什么在.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/中修复

Ju *_*Liu 5

我已经对这个问题进行了一些探讨,我认为这是由于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)
Run Code Online (Sandbox Code Playgroud)

产量

false
true
[]
Run Code Online (Sandbox Code Playgroud)

所以MC_CONST定义了常量,但是它不能作为类的局部常量(我将错误传递给各种方法以禁用常量分辨率并将其保持在该类的本地),这应该是确实的.如果我们查看Module#常量的文档,它会说:

返回mod中可访问的常量名称数组.除非将all参数设置为false,否则这包括任何包含的模块中的常量名称(示例在部分的开头).

另见Module :: const_defined?.

所以它告诉我们检查const_defined?以更好地理解行为constants,但这两种方法给出了不同的结果!


此外,在其他Ruby实现上,此代码按预期工作.

在JRuby 1.7.9上,它产生:

false
true
[:MC_CONST]
Run Code Online (Sandbox Code Playgroud)

在Rubinius 2.2.1上,它产生:

false
true
[:MC_CONST]
Run Code Online (Sandbox Code Playgroud)

这是预期的行为:)