2009-10-04 10 views
5
class A 
    do_something_from_b 

    def method_in_a 
    end 
end 

module B 
    def self.included base 
    base.extend ClassMethods 
    end 

    module ClassMethods 
    def do_something_from_b 
     A.class_eval do 
     alias_method :aliased_method_in_a, :method_in_a 
     end 
    end 
    end 
end 

A.send(:include, B) 

Quel codice non sarà riuscito perché quando do_somethind_from_b viene chiamato, method_in_a non esiste ancora.codice in esecuzione dopo le lezioni è a pieno carico

Quindi c'è un modo per collegare in class A dopo che è stato completamente caricato, senza mettere la chiamata do_something_from_b a fine class A?

Modifica: Come sottolineato, ci sono altre cose che non funzionano nel codice, ma questo è oltre il punto. Voglio solo illustrare ciò che voglio realizzare, che è eseguire alcuni codice dopo una classe è chiusa (non importa che possa essere riaperta a volontà). E ora so che probabilmente non è possibile.

Grazie!

+0

Vorrei suggerire di pubblicare un esempio funzionante, con qualsiasi commento su "Come faccio a fare questo lavoro". In questo caso, dovrebbe essere solo una riga, ma questo codice sembra essere rotto in vari modi ... – DigitalRoss

+3

Inoltre, le classi ruby ​​sono aperte, quindi non c'è mai un punto nel tempo in cui una classe è completamente caricata. –

+0

Sam, grazie per il promemoria. Quindi credo che a causa di ciò, è impossibile fare ciò che volevo. – Ivan

risposta

5

In Ruby una classe non viene mai caricata completamente. Puoi riaprirlo quando vuoi.

class A 
    def method_in_a 
    … 
    end 
end 

Si può fare tardi, non importa dove il codice è (anche in un altro file di codice sorgente).

class A 
    alias :aliased_method_in_a :method_in_a 
end 

o si potrebbe farlo nel modo l'avete scritto (che è esattamente lo stesso del precedente codice)

A.class_eval do 
    alias :aliased_method_in_a :method_in_a 
end 

Come lei ha sottolineato A # method_in_a deve esistere al momento alias IT . Per assicurarti che ciò sia vero, potresti fare

require "file_of_class_a" 

prima di fare l'alias. Se non si sa quando verrà creato il metodo A # method_in_a si potrebbe fare

class A 
    def self.method_added(name) 
    alias :aliased_method_in_a :method_in_a if name == :method_in_a 
    end 
end 

A.method_added viene chiamato automaticamente ogni volta che un metodo in una viene definito.

+0

johannes, non posso ringraziarti abbastanza. Questo metodo è estremamente utile. Sospetto che possa essere un successo in termini di prestazioni, ma speriamo che non sia troppo bello. A proposito, non so cosa succede con un alias "semplice", ma sto usando alias_method_chain di Rails, che innesca method_added in un ciclo infinito, quindi ho dovuto usare una variabile di classe per vedere se il metodo era già stato alias – Ivan

+1

Ed ecco un po 'più di informazioni su method_added: http://blog.sidu.in/2007/12/rubys-methodadded.html – Ivan

+0

L'ho provato con un semplice alias e non si è verificato alcun caso di ricorsione. – johannes

Problemi correlati