如何 - 没有继承 - 覆盖一个类方法并从新方法中调用原始方法?
-
08-07-2019 - |
题
我找到了一个成功覆盖Time.strftime
的源代码:
class Time
alias :old_strftime :strftime
def strftime
#do something
old_strftime
end
end
问题是,strftime
是一种实例方法。我需要覆盖Time.now
- 一个类方法 - 在任何调用者获取我的新方法的同时,新方法仍然调用原始的.now
方法。我看了alias_method
并且没有成功。
解决方案
有时难以理解,但你需要打开<!>“eigenclass <!>”;这是与特定类对象关联的单例。这个语法是class <!> lt; <!> lt;自我...结束。
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
不隶属于 StackOverflow