In Ruby 1.8.7, the documentation does not list ARGF
under classes and modules, and ARGF
isn't a class or a module:
ARGF.class # => Object
In Ruby 1.9.3, the documentation has ARGF
under classes and modules, but I see this:
ARGF.class # => ARGF.class
ARGF.superclass # => NoMethodError: undefined method `superclass' for ARGF:ARGF.class
ARGF.class.superclass # => Object
ARGF
as a class when the actual class is something else? Or are they the same thing?ARGF.class
a metaclass, a virtual class, singleton class, or something else?ARGF
is implemented in C and you can do weird things in it. The ARGF
class is defined there first. It is not set to any constant in Ruby, but its name is set to "ARGF.class".
Then ARGF
constant is set to an instance of that class.
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);
Here is a Ruby code that is doing roughly the same thing.
argf_class = Class.new
def argf_class.name
"ARGF.class"
end
argf = argf_class.new
ARGF = argf
It does not look reasonable in Ruby, but in C it is fine. Although, I think the class could be set to ARGFClass
like NilClass
, TrueClass
, FalseClass
, so that it is not confusing.
I don't know the history of the change. I think Ruby core folks wanted to get ARGF
into the docs and this was the simplest way. (RDoc can't show documentation for singleton objects.)
It seems correct that ARGF
is not a class or a module.
class ARGF
end
# => TypeError: ARGF is not a class
module ARGF
end
# => TypeError: ARGF is not a module
The documentation lists ARGF
under class, but other than that, it does not say it is a class. Probably, it was not intended that ARGF
handled as a class, and it is wrong of the documentation to have listed as such. It is the documentation's bug.
It looks like ARGF
if the only instance of a certain class, which lacks a literal, and the only way to refer to it is to call ARGF.class
.
ARGF.class.class
# => Class
ARGF.class.ancestors
# => [ARGF.class, Enumerable, Object, Kernel, BasicObject]
The usual relation between class and its instance holds for ARGF.class
and ARGF
.
ARGF.is_a?(ARGF.class)
# => true
ARGF.kind_of?(ARGF.class)
# => true
If we capture the objects and look at them using just pure Ruby we can see a few things:
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]
For some reason, the developers have explicitly set the class.name value to return ARGF.class
, which is generally uncommon but is used internally in Ruby for constants that should never be accessed directly.
We can instantiate objects with the ARGFClass exactly the same as any other class. That means it is a real Ruby class:
1.9.3 (Object#main):0 > argfinstance = ARGFClass.new
=> ARGF
1.9.3 (Object#main):0 > argfinstance.inspect
=> "ARGF"
It's not just returning the singleton when you call #new either:
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
The Ruby developers have intentionally named the ARGF.class
in such a way that it can't be referenced directly by name, but it is a real class and ARGF
is a real object.
It has a lot of the same methods as an IO object, and in fact is defined in the io.c
source file. It also has the Enumerable module mixed in so it supports all the each/inject/map functionality.
edit: The documentation lists ARGF
as a class. However, its actually a constant referencing a singleton instance of the oddly named ARGF.class
class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With