Estaba estudiando sobre la metaclase de Ruby. Yo leí esta respuesta en la que se describe muy bien lo que es metaclase. Se muestra allí cuando se crea una clase, creará dos objetos. Lo cual es comprensible. Uno para la clase en sí y otro para su metaclase. Pero cuando lo intento, veo que está creando tres objetos.
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
Estoy usando Ruby - 2.5.1.
¿Alguien puede ayudarme a entender esto?
Actualizar:
La referencia SO Post que añadí está utilizando ruby-1.9.1 o mayor, como el método count_objectspara ObjectSpacese introdujo en 1.9.1. Parece que el T_CLASSconteo siempre ha sido 3 (probado con ruby-1.9.3-p551).
Entonces, hasta ahora sigue siendo un misterio por qué esta respuesta . Ruby bajo un microscopio también dice que el recuento es 2.
ruby
ruby-1.9.3
Rafayet Monon
fuente
fuente

2. Cuando se ejecuta con IRB la diferencia es3. IRB parece estar haciendo algo por su cuenta. ¿Obtuviste tu resultado usando IRB? En cualquier caso, losObjectSpacemétodos de ejecución ejecutados dentro de IRB (y Pry, tal vez) dan resultados distorsionados.--disable-jit --disable-gems --disable-did_you_mean, obtengo aún menos, pero el conteo siempre es consistente en las ejecuciones y siempre difiere según 3. Estoy usando YARV 2.7.1 de Homebrew en macOS "Catalina" 10.15.4.class Test; endla diferencia en conteo es 2; cuando ejecutoclass Test; def self.t; end; endla diferencia es 3, aparentemente porque crear el método de clase creaTestla clase singleton. Sin embargo, si ejecutoObjectClass.each_object(Class)antes y después, la diferencia en las matrices es[Test]en el primer caso y[Test, #<Class:Test>]en el segundo.Respuestas:
De https://bugs.ruby-lang.org/issues/16788 :
Modificando un poco el código de la pregunta:
Obtengo los siguientes resultados:
Lo probé con Ruby 2.6 y 2.0 dentro y fuera de una consola (los números difieren pero la diferencia es la misma) y @SajibHassan con 1.9.3 (versión en la que
count_objectsse introdujo el método ). Esto significa que la diferencia siempre ha sido 3 y que la primera clase singleton creada no es accesible para el usuario.El libro Ruby Under a Microscope (escrito en 2012 después del lanzamiento de Ruby 2.1) también describe la creación de solo dos metaclases, que no coinciden con el resultado que obtenemos.
Tenga en cuenta que los métodos como
Module#prepend(introducido en Ruby 2.0), que fue mencionado por @ JörgWMittag en los comentarios como la posible razón de esta clase adicional, useT_ICLASS. Verifique el commit en el que se introdujo el método para más detalles. Supongo que esoT_ICLASSsignifica clase interna y, en consecuencia, las clases internas no deberían ser visibles para el usuario (lo cual tiene sentido). Sin embargo, no estoy seguro de por qué algunosT_CLASSson accesibles para el usuario y otros no.fuente