没有继承的人如何重写一个类方法并从新方法中调用原始方法?
问题描述:
我发现,成功地推翻Time.strftime
这样一个来源:没有继承的人如何重写一个类方法并从新方法中调用原始方法?
class Time
alias :old_strftime :strftime
def strftime
#do something
old_strftime
end
end
麻烦的是,strftime
是一个实例方法。我需要重写Time.now
- 一种类方法 - 以便让任何呼叫者获得我的新方法,而新方法仍然调用原始方法.now
。我看过alias_method
,但没有成功。
答
这是有点难以有时身边让你的头,但你需要打开“eigenclass”,这是一类特殊对象关联的单。这个语法是类< < 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),红宝石嘲讽/斯塔宾框架会为你轻松做到这一点。例如,使用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