什么是Ruby 1.9中的ARGF.class?

时间:2012-09-05 04:50:12

标签: ruby class ruby-1.9

在Ruby 1.8.7中,the documentation未在类和模块下列出ARGFARGF不是类或模块:

ARGF.class # => Object

在Ruby 1.9.3中,the documentation在类和模块下有ARGF,但我看到了:

ARGF.class # => ARGF.class
ARGF.superclass # => NoMethodError: undefined method `superclass' for ARGF:ARGF.class
ARGF.class.superclass # => Object
  • 为什么Ruby 1.9文档将ARGF作为一个类,而实际的类是其他的?或者他们是一回事吗?
  • ARGF.class是元类,虚拟类,单例类还是别的什么?

4 个答案:

答案 0 :(得分:27)

ARGF在C中实现,您可以在其中执行奇怪的操作。首先定义ARGF类。它没有设置为Ruby中的任何常量,但其名称设置为“ARGF.class”。 然后将ARGF常量设置为该类的实例。

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);

这是一个大致相同的Ruby代码。

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

在Ruby中看起来不合理,但在C中它很好。虽然,我认为课程可以设置为ARGFClass,例如NilClassTrueClassFalseClass,这样就不会造成混淆。

我不知道变化的历史。我认为Ruby核心人员想要ARGF进入文档,这是最简单的方法。 (RDoc无法显示单例对象的文档。)

答案 1 :(得分:7)

ARGF不是类或模块似乎是正确的。

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

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

文档列出了类下的ARGF,但除此之外,它并没有说它是一个类。也许,ARGF并不打算将其作为一个类处理,并且文档列出的是错误的。这是文档的错误。

如果某个类的唯一实例(缺少文字),并且引用它的唯一方法是调用ARGF,则看起来像ARGF.class

ARGF.class.class
# => Class

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

类及其实例之间的通常关系适用于ARGF.classARGF

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

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

答案 2 :(得分:4)

如果我们捕获对象并使用纯Ruby来查看它们,我们可以看到一些东西:

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]

由于某种原因,开发人员已经明确地将class.name值设置为返回ARGF.class,这通常不常见,但在Ruby内部用于永远不能直接访问的常量。

我们可以使用ARGFClass实例化对象与任何其他类完全相同。这意味着它是一个真正的Ruby类:

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

当你打电话给#new时,它不只是返回单身人士:

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

Ruby开发人员故意将ARGF.class命名为不能通过名称直接引用它,但它是一个真正的类,而ARGF是一个真实的对象。

它有许多与IO对象相同的方法,实际上是在io.c源文件中定义的。它还混合了Enumerable模块,因此它支持所有的每个/ inject / map功能。

编辑:文档将ARGF列为一个类。但是,它实际上是一个常量引用奇怪命名的ARGF.class类的单例实例。

参考

答案 3 :(得分:0)

ARGF是一个Array类。 在https://github.com/DouglasAllen/Ruby_core_ri_doc/tree/master/ARGF看一些例子 也许不是名字,但你可以像任何数组一样使用它,除了你可以将命令行参数传递给它。尝试添加其他内容只是为了看看会发生什么。