猴子修补对象产生奇怪的结果

发布于 2024-12-22 10:30:59 字数 1305 浏览 4 评论 0原文

我正在将 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

独木成林 2024-12-29 10:30:59

to_hash 方法用于识别强制哈希的对象。从这个意义上说,它的行为类似于 to_aryto_str。您实现的方法更像是 to_ato_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 like to_ary or to_str. The method you implemented is more like to_a or to_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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文