2008-11-13 13 views
9

fand ich eine Quelle, die erfolgreich Time.strftime wie dieses overrode:Wie überschreibt man - ohne Vererbung - eine Klassenmethode und ruft das Original innerhalb der neuen Methode auf?

class Time 
    alias :old_strftime :strftime 
    def strftime 
    #do something 
    old_strftime 
    end 
end 

Das Problem ist, ist eine Instanz strftime Methode. Ich muss Time.now - eine Klassenmethode - überschreiben, so dass jeder Aufrufer meine neue Methode erhält, während die neue Methode immer noch die ursprüngliche Methode .now aufruft. Ich habe alias_method angesehen und habe keinen Erfolg gehabt.

Antwort

11

Das ist irgendwie schwer Ihren Kopf herum manchmal, aber Sie müssen die „Eigenklasse“ öffnen, welche die Singleton mit einem bestimmten Klassenobjekt zugeordnet ist . Die Syntax hierfür lautet Klasse < < 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 
2

Klassenmethoden sind nur Methoden. Ich empfehle dagegen hoch, aber Sie haben zwei gleichwertige Möglichkeiten:

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 
1

Wenn das Sie es zu Testzwecken außer Kraft setzen müssen (der Grund, warum ich möchte normalerweise Time.now außer Kraft zu setzen), Rubin spöttischen/stubbing Frameworks wird dies leicht für Sie tun. Zum Beispiel mit RSpec (der flexmock verwendet):

Time.stub!(:now).and_return(Time.mktime(1970,1,1)) 

By the way, ich empfehle die Notwendigkeit vermieden Klassen eine überschreibbar Uhr, indem Time.now Stub:

class Foo 
    def initialize(clock=Time) 
    @clock = clock 
    end 

    def do_something 
    time = @clock.now 
    # ... 
    end 
end 
0

I habe versucht herauszufinden, wie man eine Instanzmethode mit Modulen überschreiben kann.

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