ruby - 为什么 ruby​​ 在创建一个类后会创建 3 个对象?

标签 ruby ruby-1.9.3

我正在研究 Ruby 的元类。我read this answer在那里很好地描述了元类是什么。它显示在创建一个类时它将创建两个对象。这是可以理解的。一种用于类本身,一种用于它的元类。但是当我自己尝试时,我发现它正在创建三个对象。

puts "Before Class Creation object count - #{ObjectSpace.count_objects[:T_CLASS]}"
class Test
  def self.foo # test_singleton
    p 'Printed from method #foo'
  end

  def bar # test
    p 'Printed from method #bar'
  end
end
puts "After Class Creation object count - #{ObjectSpace.count_objects[:T_CLASS]}"

###############

Before Class Creation object count - 949
After Class Creation object count - 952

我正在使用 Ruby - 2.5.1 .

谁能帮我理解这个?

更新:

reference SO我添加的帖子使用 ruby​​-1.9.1 或更高版本,作为方法 count_objectsObjectSpace在 1.9.1 中引入。看来T_CLASS计数始终为 3(尝试使用 ruby-1.9.3-p551 )。

所以,直到现在仍然是一个谜 this answer . Ruby under a microscope还说计数是 2。

最佳答案

来自 https://bugs.ruby-lang.org/issues/16788 :

Creating a class automatically creates a singleton class (which is not accessible to the user). Referencing the singleton class of a class automatically creates a singleton class of that singleton class. This is to keep consistency of the inheritance structure of metaclasses. Otherwise, class methods wouldn't inherit from the superclass's metaclass, which is necessary as the superclass's class methods should be available as the subclass's class methods.



稍微修改一下问题代码:
$old_classes = []
def print_objects
  new_classes = []
  ObjectSpace.each_object(Class){|x| new_classes << x}
  puts "New classes: #{new_classes - $old_classes}" unless $old_classes.empty?
  puts "Counts: #{ ObjectSpace.count_objects[:T_CLASS] }"
  $old_classes = new_classes
end

print_objects

class Test
end
puts 'Test class created'
print_objects

class Test
  def self.foo
  end 
end
puts 'Test singleton class referenced'
print_objects

我得到以下结果:
Counts: 690
Test class created
New classes: [Test]
Counts: 692
Test singleton class referenced
New classes: [#<Class:Test>]
Counts: 693

我在控制台内部和外部使用 Ruby 2.6 和 2.0(数字不同但区别相同)和 @SajibHassan 与 1.9.3(引入了方法 count_objects 的版本)进行了尝试。
这意味着差异始终为 3,并且用户无法访问创建的第一个单例类。

Ruby Under a Microscope (写于 2012 年 Ruby 2.1 发布后)也描述了只创建了两个元类,这与我们得到的结果不符。

注意像 Module#prepend 这样的方法(在 Ruby 2.0 中引入),@JörgWMittag 在评论中提到作为这个额外类的可能原因,使用 T_ICLASS .查询 the commit in which the method was introduced详情。我猜是 T_ICLASS代表内部类,因此内部类不应该对用户可见(这是有道理的)。我不知道为什么有些 T_CLASS用户可以访问,而其他一些则不能。

关于ruby - 为什么 ruby​​ 在创建一个类后会创建 3 个对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61031735/

相关文章:

ruby - 在 Ruby 的正则表达式中,前瞻和后视概念如何支持这种零宽度断言概念?

ruby - 如何在 Ruby 中使用 before 和 after 包装方法?

ruby-on-rails - 使用 Ruby 1.9.3 进行 ruby​​ 调试?

regex - 如何用特殊字符替换字符串中的多个字符

ruby-on-rails - 是否可以在Ruby ActiveAdmin中从索引 block 外部的redis进行批量读取?

ruby - 如何巧妙地进行数组加法?

ruby - 为什么 `block_given?` 在这个动态定义的方法中不起作用?

ruby-on-rails - Rails 承认关联,但不显示数据

html - 使用 Selenium 在 Ruby 中选中复选框时访问出现的类属性

Ruby 1.9.3 Teeny 版本