Ruby:为什么要调用to_ary?

时间:2012-01-22 11:22:51

标签: ruby metaprogramming method-missing

我正在学习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会尝试将我的对象转换为数组来打印它?

我用Google搜索并找到了这些相关链接:

这些也讨论了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

1 个答案:

答案 0 :(得分:16)

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

  

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

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

to_s内部使用在Ruby文档中没有很好的记录(Matz在他的 Ruby Programming Language 一书中指出了这一点。)

另一方面,to_aryprint方法不会调用p,而只调用to_ary

Sidenote :有趣的是,to_s必须返回真正的to_ary对象,而不是定义Array方法或其他内容的对象:

each