Ruby 为什么迭代内外的对象不同?

Ruby 为什么迭代内外的对象不同?,ruby,constants,Ruby,Constants,我将一个类分配给常量Foo,并将Foo重新分配给其他对象: class Foo; end Foo = nil 在main环境中,Foo指的是新分配的对象: p Foo # => nil 但是,在某种类型的迭代中,(我不确定是哪种迭代),Foo引用了前面的对象: ObjectSpace.each_object(Class).select{|c| c.name == "Foo"} .each{|c| p c, c.instance_of?(Class)} # => Foo

我将一个类分配给常量
Foo
,并将
Foo
重新分配给其他对象:

class Foo; end
Foo = nil
main
环境中,
Foo
指的是新分配的对象:

p Foo # => nil
但是,在某种类型的迭代中,(我不确定是哪种迭代),
Foo
引用了前面的对象:

ObjectSpace.each_object(Class).select{|c| c.name == "Foo"}
.each{|c| p c, c.instance_of?(Class)}
# => Foo
     true

这是为什么?

您创建的类存在,只要不进行垃圾收集,就可以从主ObjectSpace访问该类

常量名
Foo
只是对类对象的引用。它的内部名称仍然是“Foo”,即使通过其他变量或常量名称访问也是如此

尝试这样做,以证明即使“重命名”
a
,类的名称仍然是“Foo”:


Foo
绑定到块内外的
nil
。你凭什么认为不是?您甚至没有在块内部引用
Foo

nil
赋值给常量
Foo
不会影响所创建的类。它仍然存在,尽管您不能再使用
Foo
引用它(除非您再次将类对象指定给
Foo

关于
名称
,创建具有以下内容的类:

class Foo; end
Foo.name
# => "Foo"
将其分配给contant
Foo
,如下所示:

Foo = Class.new
Foo.name
# => "Foo"
它还设置了它的
名称
,但这并不使它成为一个类。您也可以创建没有名称的类:

foo = Class.new
foo.name
# => nil
将未命名类指定给常数将设置其名称:

Bar = foo
foo.name
# => "Bar"
设置后,它不会更改:

Baz = foo
foo.name
# => "Bar"

这来自Jörg W Mittag对我的答案的评论。块内的对象返回
Foo
作为其名称,这是一个类。这与常量
Foo
的值有什么关系?大写的名称是常量。以大写字母开头的变量是常量。但是块中仅有的两个变量是
c
,它甚至不是常数,和
Class
它是常数,但不是
Foo
。它不被任何文字表达式引用,但相关对象
c
有一个名称
Foo
。(请注意,我避免使用“变量”一词,因为常数不是变量。)这是否意味着两个不同的对象可以共享同一个名称,并且当使用该名称调用时,有某种优先级决定引用哪个对象?这里只有一个对象。我指的是
nil
,它被称为
Foo
,并且是原始类对象,它也有名称
Foo
。您所说的“它也有名称
Foo
”是什么意思?对象在Ruby中没有名称。方法和变量有名称,但方法和变量不是对象。@sawa您可以多次声明“Foo”类,它仍然引用一个且唯一一个类,功能将根据需要附加到它。对于
类没有
name=
方法,尝试动态创建一个类将导致创建一个匿名类,而不可能更改其名称。我知道了。我似乎混淆了常量“named”
Foo
和属性为
Foo
的类。谢谢你的帮助。
Bar = foo
foo.name
# => "Bar"
Baz = foo
foo.name
# => "Bar"