ruby class ruby-1.9

¿Qué es ARGF.class en Ruby 1.9?



ruby-1.9 (4)

ARGF es una clase de Array. vea algunos ejemplos en https://github.com/DouglasAllen/Ruby_core_ri_doc/tree/master/ARGF Tal vez no sea por su nombre, pero podrá decirlo usándolo como cualquier matriz, excepto que puede pasarle argumentos de línea de comandos. Intenta agregar algo más para ver qué pasa.

En Ruby 1.8.7, la documentación no enumera ARGF en clases y módulos, y ARGF no es una clase o un módulo:

ARGF.class # => Object

En Ruby 1.9.3, la documentación tiene ARGF en clases y módulos, pero veo esto:

ARGF.class # => ARGF.class ARGF.superclass # => NoMethodError: undefined method `superclass'' for ARGF:ARGF.class ARGF.class.superclass # => Object

  • ¿Por qué la documentación de Ruby 1.9 coloca a ARGF como una clase cuando la clase real es otra cosa? ¿O son la misma cosa?
  • ¿Es ARGF.class una metaclase, una clase virtual, una clase singleton o algo más?

Parece correcto que ARGF no es una clase o un módulo.

class ARGF end # => TypeError: ARGF is not a class module ARGF end # => TypeError: ARGF is not a module

La documentación enumera ARGF en la clase, pero aparte de eso, no dice que sea una clase. Probablemente, no se pretendía que ARGF manejara como una clase, y no es correcto que la documentación se incluya como tal. Es el error de la documentación.

Parece que ARGF es la única instancia de una determinada clase, que carece de un literal, y la única manera de referirse a ella es llamar a ARGF.class .

ARGF.class.class # => Class ARGF.class.ancestors # => [ARGF.class, Enumerable, Object, Kernel, BasicObject]

La relación habitual entre la clase y su instancia es ARGF.class para ARGF.class y ARGF .

ARGF.is_a?(ARGF.class) # => true ARGF.kind_of?(ARGF.class) # => true


Si capturamos los objetos y los observamos usando solo Ruby puro, podemos ver algunas cosas:

1.9.3 (Object#main):0 > ARGFClass = ARGF.class => ARGF.class 1.9.3 (Object#main):0 > ARGFClass.name => "ARGF.class" 1.9.3 (Object#main):0 > ARGFClass.class => Class 1.9.3 (Object#main):0 > ARGFClass.superclass => Object 1.9.3 (Object#main):0 > ARGFClass.ancestors => [ARGF.class, Enumerable, Object, JSON::Ext::Generator::GeneratorMethods::Object, PP::ObjectMixin, Kernel, BasicObject]

Por alguna razón, los desarrolladores han establecido explícitamente el valor de class.name para devolver ARGF.class , que generalmente es poco común pero se usa internamente en Ruby para las constantes a las que nunca se debe acceder directamente.

Podemos instanciar objetos con ARGFClass exactamente igual que cualquier otra clase. Eso significa que es una verdadera clase de Ruby:

1.9.3 (Object#main):0 > argfinstance = ARGFClass.new => ARGF 1.9.3 (Object#main):0 > argfinstance.inspect => "ARGF"

No es solo devolver el singleton cuando llamas #new tampoco:

1.9.3 (Object#main):0 > argfinstance == ARGF => false 1.9.3 (Object#main):0 > argfinstance.object_id => 70346556507420 1.9.3 (Object#main):0 > ARGF.object_id => 70346552343460

Los desarrolladores de Ruby han nombrado intencionalmente ARGF.class de tal manera que no puede ser referenciado directamente por su nombre, pero es una clase real y ARGF es un objeto real.

Tiene muchos de los mismos métodos que un objeto IO y, de hecho, se define en el archivo fuente io.c También tiene el módulo Enumerable mezclado, por lo que es compatible con todas las funciones de / inyectar / mapa.

Edición: La documentación enumera ARGF como una clase. Sin embargo, en realidad es una referencia constante a una instancia de singleton de la clase ARGF.class , ARGF.class nombre es extraño.

Referencias


ARGF está implementado en C y puedes hacer cosas raras en él. La clase ARGF se define allí primero. No se establece en ninguna constante en Ruby, pero su nombre se establece en "ARGF.class". Entonces, la constante ARGF se establece en una instancia de esa clase.

rb_cARGF = rb_class_new(rb_cObject); rb_set_class_path(rb_cARGF, rb_cObject, "ARGF.class"); /* ... */ argf = rb_class_new_instance(0, 0, rb_cARGF); rb_define_global_const("ARGF", argf);

Aquí hay un código de Ruby que está haciendo más o menos lo mismo.

argf_class = Class.new def argf_class.name "ARGF.class" end argf = argf_class.new ARGF = argf

No parece razonable en Ruby, pero en C está bien. Aunque, creo que la clase podría establecerse en ARGFClass como NilClass , TrueClass , FalseClass , para que no sea confuso.

No sé la historia del cambio. Creo que la gente de Ruby Core quería que ARGF en los documentos y esta era la forma más sencilla. (RDoc no puede mostrar documentación para objetos singleton).