猴子修补对象会产生奇怪的结果
Posted
技术标签:
【中文标题】猴子修补对象会产生奇怪的结果【英文标题】:monkey patching Object produces strange results 【发布时间】:2012-01-24 17:47:38 【问题描述】:我正在将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>'
在 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 位 RUBYGEMS 版本:1.8.12【问题讨论】:
谁会想到更改低级对象会产生意想不到的后果,疯了!要发现 为什么 它会以这种方式破坏事物(在pry
下更令人兴奋),您甚至可能需要跟踪一些 C,以确定为什么 to_hash
会特别破坏事物——也许是什么else 试图定义它,但没有定义它,因为它已经存在。谁知道。 to_hashish
工作正常,因此显然与符号相关。
为什么要关闭/拒绝投票?想知道为什么这会破坏某些东西(尤其是它的方式)是有效的,即使感到惊讶有点好笑。
谢谢,当我继续打破其他东西的道路上时,我会调查 pry...看起来很有趣
使用 ruby 1.9.3p0,run_test1
可以正常工作。 run_test2
没有。
【参考方案1】:
to_hash
方法用于识别强制为 Hash 的对象。从这个意义上说,它的行为类似于to_ary
或to_str
。您实现的方法更像to_a
或to_s
。
很多 Ruby 代码,包括 Ruby 核心代码,都会检查 to_hash
以确定参数是否是选项哈希 (arg.respond_to? :to_hash
),然后从那里遵循不同的执行路径。一些代码检查对象是否是真正的散列(Hash === arg
),这会变得更加混乱。
您可能希望将您的方法命名为 to_h
或类似名称。
【讨论】:
以上是关于猴子修补对象会产生奇怪的结果的主要内容,如果未能解决你的问题,请参考以下文章
直接访问与在开发工具中读取对象时访问 javascript 属性会产生不同的结果