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

时间:2013-05-13 15:16:48

标签: 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
     true

为什么会这样?

3 个答案:

答案 0 :(得分:4)

nil分配给常量Foo不会影响创建的类。它仍然存在,但您不能再使用Foo引用它(除非您再次将类对象重新分配给Foo)。

class Foo; end
Foo.object_id
# => 70210590718440
Foo = nil
Foo.object_id
# => 4
Foo = ObjectSpace._id2ref(70210590718440)
Foo.object_id
# => 70210590718440

关于name,创建一个类:

class Foo; end
Foo.name
# => "Foo"

将其分配给内容Foo,就像:

Foo = Class.new
Foo.name
# => "Foo"

它还设置了name,但这不会使它成为一个类。您也可以创建没有名称的类:

foo = Class.new
foo.name
# => nil

将未命名的类分配给常量设置其名称:

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

设置后,它不会改变:

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

答案 1 :(得分:2)

您创建的类存在且可以从主ObjectSpace访问,只要它不是垃圾回收。

常量名Foo仅仅是对类对象的引用。即使通过其他变量或常量名称访问,其内部名称仍为“Foo”。

试试这个,为了证明即使'重命名'a,该类的名称仍然是“Foo”:

class Foo; end
a = Foo
Foo = nil
puts a.name # prints Foo

答案 2 :(得分:1)

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