Ruby:为什么 put 调用 to_ary?
我正在学习 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 在调用 put 时调用 to_ary?为什么 Ruby 会尝试将我的对象转换为数组只是为了打印它?
我用谷歌搜索并找到了这些相关链接:
- http: //tenderlovemaking.com/2011/06/28/til-its-ok-to-return-nil-from-to_ary/
- http://yehudakatz.com/2010/01/02/the-craziest -fing-bug-ive-ever-seen/
这些还讨论了 method_missing 和 to_ary 陷阱,但没有具体讨论为什么 put 会调用 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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
puts
是$stdout.puts
的同义词。 $stdout 是一个IO
类,因此请查看 IO.puts:这意味着
puts
方法旨在写入多行输出。因此,它尝试在对象上调用to_ary
方法,如果定义了to_ary
,则在新行上打印返回的Array
的每个元素, elseputs
调用to_s
方法。Ruby 文档中确实没有很好地记录
to_ary
内部用法(Matz 在他的The Ruby Programming Language 书中指出了这一点)。另一方面,方法
print
和p
不调用to_ary
,仅调用to_s
。旁注:有趣的是,
to_ary
必须返回真正的Array
对象,而不是定义each
方法或其他内容的对象:puts
is a synonym for$stdout.puts
. $stdout is anIO
class, so look at the documentation for IO.puts:This mean that
puts
method is intended to write several lines of output. Thus it tries to callto_ary
method on an object and ifto_ary
is defined, then prints each element of the returnedArray
on a new line, elseputs
callsto_s
method.to_ary
internal usage is really not well documented in the Ruby documentation (Matz points this out in his The Ruby Programming Language book).Methods
print
andp
on the other hand don't callto_ary
, onlyto_s
.Sidenote: Interesting, that
to_ary
must return realArray
object, not an object definingeach
method or something else: