【问题标题】:Ruby: why does puts call to_ary?Ruby:为什么 puts 调用 to_ary?
【发布时间】:2012-02-16 03:45:01
【问题描述】:

我正在学习 Ruby 中的元编程,并且正在尝试通过 method_missing 和 define_method 定义缺失的方法。我遇到了一些意外的行为,想知道是否有人可以解释这一点。这是我的课:

class X
  def method_missing(m, *args, &block)
    puts "method #{m} not found. Defining it."
    self.class.send :define_method, m do
      puts "hi from method #{m}"
    end
    puts "defined method #{m}"
  end  
end

现在,这段代码:

x = X.new

x.some_method
puts
x.some_method
puts
puts x

产生输出:

method some_method not found. Defining it.
defined method some_method

hi from method some_method

method to_ary not found. Defining it.
defined method to_ary
#<X:0x007fcbc38e5030>

我不明白的是最后一部分:为什么 Ruby 在调用 puts 时调用 to_ary?为什么 Ruby 会尝试将我的对象转换为数组来打印它?

我搜索了一下,发现了这些相关链接:

这些还讨论了 method_missing 和 to_ary 陷阱,但没有具体讨论为什么 puts 会调用 to_ary。

我还应该提到,当我定义一个 to_s 时,行为不会改变,例如

def to_s
  "I'm an instance of X"
end

“puts x”的输出是:

method to_ary not found. Defining it.
defined method to_ary
I'm an instance of X

【问题讨论】:

    标签: ruby metaprogramming method-missing


    【解决方案1】:

    puts$stdout.puts 的同义词。 $stdout 是一个IO 类,因此请查看IO.puts 的文档:

    像使用 IO#print 一样将给定的对象写入 ios。写入记录 任何尚未以结尾的分隔符(通常是换行符) 换行序列。如果使用数组参数调用,则写入每个 新行上的元素。

    这意味着puts 方法打算写几行输出。因此,它尝试在对象上调用to_ary 方法,如果定义了to_ary,则在新行上打印返回的Array 的每个元素,否则puts 调用to_s 方法。

    to_ary 内部使用在 Ruby 文档中确实没有很好地记录(Matz 在他的Ruby 编程语言一书中指出了这一点)。

    另一方面,方法printp 不调用to_ary,只调用to_s

    旁注:有趣的是,to_ary 必须返回真正的 Array 对象,而不是定义 each 方法或其他东西的对象:

    class Test
      def to_ary
        10.downto(1)
      end
    end
    
    puts Test.new
    
    #TypeError: can't convert Test to Array (Test#to_ary gives Enumerator)
    #        from (irb):28:in `puts'
    #        from (irb):28:in `puts'
    #        from (irb):28
    

    【讨论】:

    • 谢谢。我认为本质是“to_ary 内部用法在 Ruby 文档中确实没有很好地记录”:) 我刚刚阅读了 IO.puts 文档,他们没有明确提到 to_ary,我认为这应该更清楚。感谢您指向“The Ruby Programming Language”一书,可能会检查一下。
    猜你喜欢
    • 2019-12-01
    • 2012-02-18
    • 2019-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-14
    • 2010-10-11
    • 2012-11-28
    相关资源
    最近更新 更多