如何 – 没有inheritance – 覆盖类方法并从新方法中调用原始方法?
我找到了一个成功覆盖Time.strftime
源代码,如下所示:
class Time alias :old_strftime :strftime def strftime #do something old_strftime end end
麻烦的是, strftime
是一个实例方法。 我需要覆盖Time.now
– 一个类方法 – 在任何调用者获取我的新方法的同时,新方法仍然调用原始的.now
方法。 我看过alias_method
并没有成功。
这有点难以理解,但你需要打开“特征类”,这是与特定类对象相关联的单例。 这个语法是类<< self do ... end。
class Time alias :old_strftime :strftime def strftime puts "got here" old_strftime end end class Time class << self alias :old_now :now def now puts "got here too" old_now end end end t = Time.now puts t.strftime
类方法只是方法。 我强烈建议不要这样做,但你有两个相同的选择:
class Time class << self alias_method :old_time_now, :now def now my_now = old_time_now # new code my_now end end end class << Time alias_method :old_time_now, :now def now my_now = old_time_now # new code my_now end end
如果你需要为了测试目的而覆盖它(我通常想要覆盖Time.now的原因),Ruby模拟/存根框架将很容易为你做到这一点。 例如,使用RSpec(使用flexmock):
Time.stub!(:now).and_return(Time.mktime(1970,1,1))
顺便说一句,我强烈建议通过为您的类提供一个可重写的时钟来避免使用Time.now:
class Foo def initialize(clock=Time) @clock = clock end def do_something time = @clock.now # ... end end
我一直在试图弄清楚如何使用模块覆盖实例方法。
module Mo def self.included(base) base.instance_eval do alias :old_time_now :now def now my_now = old_time_now puts 'overrided now' # new code my_now end end end end Time.send(:include, Mo) unless Time.include?(Mo) > Time.now overrided now => Mon Aug 02 23:12:31 -0500 2010