我正在尝试向foo
Ruby 的Array
类添加一个实例方法,因此当它被调用时,数组的字符串元素将更改为字符串“foo”。
这可以通过猴子修补 RubyString
和Array
类来轻松完成。
class String
def foo
replace "foo"
end
end
class Array
def foo
self.each {|x| x.foo if x.respond_to? :foo }
end
end
a = ['a', 1, 'b']
a.foo
puts a.join(", ") # you get 'foo, 1, foo' as expected
现在我正在尝试使用 Ruby 2 的改进功能重写上述内容。我正在使用 Ruby 版本 2.2.2。
以下工作(在文件中,例如 ruby test.rb,但由于某种原因不在 irb 中)
module M
refine String do
def foo
replace "foo"
end
end
end
using M
s = ''
s.foo
puts s # you get 'foo'
foo
但是,在添加到Array
班级时我无法让它工作。
module M
refine String do
def foo
replace "foo"
end
end
end
using M
module N
refine Array do
def foo
self.each {|x| x.foo if x.respond_to? :foo }
end
end
end
using N
a = ['a', 1, 'b']
a.foo
puts a.join(", ") # you get 'a, 1, b', not 'foo, 1, foo' as expected
有两个问题:
- 使用新方法优化类后,
respond_to?
即使您可以在对象上调用该方法,也无法正常工作。尝试puts 'yes' if s.respond_to? :foo
在第二个代码片段的最后一行添加,你会看到“是”没有打印出来。 - 在我的 Array 改进中, String#foo 超出了范围。如果你
if x.respond_to? :foo
从 Array#foo 中删除,你会得到错误undefined method 'foo' for "a":String (NoMethodError)
。所以问题是:如何使 String#foo 细化在 Array#foo 细化中可见?
我如何克服这两个问题才能让它发挥作用?
(请不要提供不涉及细化的替代解决方案,因为这是一个理论练习,所以我可以学习如何使用细化)。
谢谢你。