我正在尝试重新定义File.dirname方法,首先将%20s更改为空格。但以下给我一个错误
class File
old_dirname = instance_method(:dirname)
define_method(:dirname) { |s|
s = s.gsub("%20"," ")
old_dirname.bind(self).call(s)
}
end
这会导致一个NameError异常:类'File'的未定义方法'dirname'
这样做的正确方法是什么?
答案 0 :(得分:4)
正如Chuck已经写过的,File::dirname
是File
类对象的单例方法(或者更准确地说是File
类对象的元类的实例方法),而不是实例方法File
班。
所以,你必须打开File
的元类,而不是File
类本身:
#!/usr/bin/env ruby
class << File
old_dirname = instance_method :dirname
define_method :dirname do |*args|
old_dirname.bind(self).(*args).gsub '%20', ' '
end
end
require 'test/unit'
class TestFileDirname < Test::Unit::TestCase
def test_that_it_converts_percent20_to_space
assert_equal '/foo bar/baz', File.dirname('/foo%20bar/baz/quux.txt')
end
end
但是,我同意@sheldonh:这违反了File::dirname
的API合约。
答案 1 :(得分:3)
小心点。
您正在改变方法的行为,而不仅仅是其实现。这通常是不好的做法,因为它削弱了API作为可靠合同的价值。
相反,请考虑将输入转换为接近接收点。
答案 2 :(得分:1)
dirname
是File的类方法,而不是实例方法,因此您只需定义一个新的实例方法。此外,别名方法的惯用方法是使用alias
。所以:
class <<File
alias old_dirname dirname
def dirname(f)
old_dirname(f.gsub("%20", " "))
end
end
class <<whatever
语法将方法添加到单个对象 - 在本例中为File类。