¿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).