30

在 Ruby 1.8.7 中,文档没有ARGF在类和模块下列出,ARGF也不是类或模块:

ARGF.class # => Object

在 Ruby 1.9.3 中,文档ARGF类和模块下,但我看到了:

ARGF.class # => ARGF.class
ARGF.superclass # => NoMethodError: undefined method `superclass' for ARGF:ARGF.class
ARGF.class.superclass # => Object
  • ARGF当实际的类是别的东西时,为什么 Ruby 1.9 文档将作为一个类放置?或者他们是同一个东西?
  • ARGF.class元类、虚拟类、单例类还是其他?
4

4 回答 4

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 中却很好。虽然,我认为可以将类设置为ARGFClasslike NilClass, TrueClass, FalseClass,以免造成混淆。

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

于 2012-09-05T05:35:11.553 回答
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
于 2012-09-05T05:10:53.607 回答
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 值显式设置为 return 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 模块,因此它支持所有 each/inject/map 功能。

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

参考

于 2012-09-06T22:46:19.203 回答
0

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

于 2012-09-09T03:53:36.780 回答