【问题标题】:Why is an object different inside and outside of an iteration?为什么迭代内部和外部的对象不同?
【发布时间】:2013-05-13 15:16:47
【问题描述】:

我将一个类分配给一个常量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

这是为什么?

【问题讨论】:

  • 这是 Jörg W Mittag 对我对this question 的回答的评论。

标签: ruby constants


【解决方案1】:

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"

【讨论】:

  • 我明白了。我似乎混淆了常量“命名”Fooname 属性为Foo 的类。感谢您的帮助。
【解决方案2】:

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

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

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

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

【讨论】:

  • 这是否意味着两个不同的对象可以共享相同的名称,并且存在某种优先级来决定使用该名称调用哪个对象?
  • 这里只有一个对象。
  • 我说的是nil,简称Foo,还有原来的类对象,也叫Foo
  • 你说的“它也有名字Foo”是什么意思?对象在 Ruby 中没有名称。方法和变量都有名称,但方法和变量不是对象。
  • @sawa 你可以随意声明一个“Foo”类,它仍然是唯一的一个类,特性会根据需要附加到它上面。 Class 类没有 name= 方法,尝试动态创建类将导致创建匿名类而无法更改其名称。
【解决方案3】:

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

【讨论】:

  • 块内的对象返回Foo作为它的名字,那是一个类。
  • 这和常量Foo的值有什么关系?
  • 大写的名字是一个常数。
  • 以大写字母开头的变量是常数。但是你的块中仅有的两个变量是c,它甚至不是一个常数,和Class,它是一个常数,但不是Foo
  • 它没有被任何文字表达式引用,但相关对象c有一个名称Foo。 (请注意,我避免使用“变量”这个词,因为常量不是变量。)
猜你喜欢
  • 2020-11-22
  • 2012-06-18
  • 1970-01-01
  • 2015-08-29
  • 2017-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-08
相关资源
最近更新 更多