【问题标题】:What is ARGF.class in Ruby 1.9?Ruby 1.9 中的 ARGF.class 是什么?
【发布时间】:2012-09-05 04:50:12
【问题描述】:

在 Ruby 1.8.7 中,the documentation 没有在类和模块下列出ARGF,并且ARGF 不是类或模块:

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 是元类、虚拟类、单例类还是其他什么?

【问题讨论】:

标签: ruby class ruby-1.9


【解决方案1】:

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 用于查找和显示 C 实现。我仍然想知道 1.8 和 1.9 之间的实际变化。 1.8 的方法是有意义的;我不知道1.9现在发生了什么。我无法想象 Ruby 人会故意引入一些令人困惑的东西,但不知何故,我无法找到语义的清晰描述。
  • 我同意它应该被命名为ARGFClass
  • @Seymon 接受,但仍有一处兴趣变化。 Ruby 1.8.7 显示 ARGF.classObject 但现在有所不同。我想这里有必要对 C 实现进行比较。不过,关于让文档作者尝试引入对单例类对象的描述的很好假设。
  • ARGF.class 不是 Object,因为它现在是一个特殊类的实例。它的名称在第二行明确设置为“ARGF.class”。我想它会像 #<0x007ffc55120d50>
【解决方案2】:

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

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

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

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

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

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

【讨论】:

    【解决方案3】:

    如果我们只使用纯 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 模块,因此它支持所有 each/inject/map 功能。

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

    参考文献

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 2011-06-28
        • 1970-01-01
        • 1970-01-01
        • 2010-09-06
        • 1970-01-01
        • 2013-02-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多