I was studying about Ruby's metaclass. I read this answer where it is nicely described what metaclass is. It's showed there when a class is created it will create two objects. Which is understandable. One for the class itself and one for it's metaclass. But when I am trying it myself I see that it is creating three objects.
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
I am using Ruby - 2.5.1.
Can anyone help me understand this one?
Update:
The reference SO post that I added is using ruby-1.9.1 or greater, as the method count_objects for ObjectSpace was introduced in 1.9.1. It seems that the T_CLASS count has always always been 3 (tried with ruby-1.9.3-p551).
So, till now it's still a mystery why this answer. Ruby under a microscope also says the count is 2.
From https://bugs.ruby-lang.org/issues/16788:
Modifying the question code a bit:
I get the following results:
I tried it with Ruby 2.6 and 2.0 both inside and outside a console (the numbers differ but the difference is the same) and @SajibHassan with 1.9.3 (version in which the method
count_objectswas introduced). This means that the difference has always been 3 and that the first singleton class created is not accessible for the user.The book Ruby Under a Microscope (written in 2012 after the release of Ruby 2.1) also describes the creation of only two metaclasses, which doesn't match the result we get.
Note that methods like
Module#prepend(introduced in Ruby 2.0), which was mentioned by @JörgWMittag in the comments as the possible reason for this extra class, useT_ICLASS. Check the commit in which the method was introduced for details. I guess thatT_ICLASSstands for internal class and consequently internal classes shouldn't be visible to the user (which makes sense). I am not sure though why someT_CLASSare accessible to the user and some others are not.