猴子修补对象产生奇怪的结果
我正在将 to_hash
破解为 Object(我并不是说这是一个好主意,只是一个实验)。当我遇到一个奇怪的问题时,IO
停止工作。
#lib/object.rb
class Object
def to_hash
self.instance_variables.inject({}) { |hash,var| hash[var.to_s.delete("@")] = self.instance_variable_get(var); hash }
end
end
#run_test1.rb
require_relative 'lib/Object'
require 'FileUtils'
puts 'run test'
#run_test2.rb
require_relative 'lib/Object'
File.open('test.txt', 'w') {|f| f.write('this is a test')}
在 run_test1 中我得到一个
<internal:lib/rubygems/custom_require>:29:in `set_encoding': wrong number of arguments (0 for 1..2) (ArgumentError)
from <internal:lib/rubygems/custom_require>:29:in `require'
from <internal:lib/rubygems/custom_require>:29:in `require'
from .../run_test1.rb:2:in `<main>'
in run_test2 我得到
run_test2.rb:3:in `initialize': No such file or directory - test.txt (Errno::ENOENT
from run_test2.rb:3:in `open'
from run_test2.rb:3:in `<main>'
(如果文件存在,则表示该文件未打开以供写入)
虽然我对它的发生并不感到惊讶 - 只是好奇,这里发生了什么?理论上应该没问题,但根本原因是什么。
相关信息:
- ruby 1.9.2p290 (2011-07-09) [i386-mingw32]
- XP SP3 32-bit
- RUBYGEMS VERSION: 1.8.12
I was hacking a to_hash
to Object (I'm not saying this is a good idea, just an experiment). When I came across an odd issue, where IO
stopped working.
#lib/object.rb
class Object
def to_hash
self.instance_variables.inject({}) { |hash,var| hash[var.to_s.delete("@")] = self.instance_variable_get(var); hash }
end
end
#run_test1.rb
require_relative 'lib/Object'
require 'FileUtils'
puts 'run test'
#run_test2.rb
require_relative 'lib/Object'
File.open('test.txt', 'w') {|f| f.write('this is a test')}
in run_test1 I get an
<internal:lib/rubygems/custom_require>:29:in `set_encoding': wrong number of arguments (0 for 1..2) (ArgumentError)
from <internal:lib/rubygems/custom_require>:29:in `require'
from <internal:lib/rubygems/custom_require>:29:in `require'
from .../run_test1.rb:2:in `<main>'
in run_test2 I get
run_test2.rb:3:in `initialize': No such file or directory - test.txt (Errno::ENOENT
from run_test2.rb:3:in `open'
from run_test2.rb:3:in `<main>'
(if the file exists it says the file is not open for writing)
While I'm not surprised it happened - just curious, What is going on here? Theoretically it should be fine, however what is the underlying cause.
The relevant info:
- ruby 1.9.2p290 (2011-07-09) [i386-mingw32]
- XP SP3 32-bit
- RUBYGEMS VERSION: 1.8.12
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
to_hash
方法用于识别强制哈希的对象。从这个意义上说,它的行为类似于to_ary
或to_str
。您实现的方法更像是to_a
或to_s
。许多 Ruby 代码(包括 Ruby 核心代码)都会检查
to_hash
来确定参数是否是选项哈希 (arg.respond_to? :to_hash
),然后从那里进行后续操作不同的执行路径。通过一些代码检查对象是否是真正的散列(Hash === arg
),这会变得更加混乱。您可能想将您的方法命名为
to_h
或类似的名称。The
to_hash
method is used to identify objects that coerce to Hash. In that sense, it behaves liketo_ary
orto_str
. The method you implemented is more liketo_a
orto_s
.Lots of Ruby code, including Ruby core code, checks for
to_hash
to figure out whether an argument is an options hash (arg.respond_to? :to_hash
) and from there on follow a different execution path. This gets even more messed up by some code checking if the object is a real hash or not (Hash === arg
).You might want to name your method
to_h
or something similar.