2012-11-15 13 views
6

Ho un modulo che consente di chiamare "Calcolatrice" che voglio includere in una classe "Prodotto". Il calcolatore estenderà "Prodotto" che copierà i metodi della classe sul Prodotto. Uno di questi metodi di classe è "memoize". L'idea è che posso fare qualcosa di simile:Come posso definire dinamicamente un metodo alias per un metodo di classe?

module Calculator 
    def self.extended(base) 
    base.memoize :foo_bar 
    end 
end 

Con lo scopo di memoizing del metodo (in particolare un metodo di classe): foo_bar. All'interno del memoize chiamo il metodo "alias_method" che tenta di creare un alias di un metodo di classe con un nome diverso (qui: foo_bar). Questo fallisce. Memoize sembra qualcosa di simile:

module Calculator (the extended module) 
    def memoize(name) 
    alias_method "memoized_#{name}", name 
    end 
end 

Quando questo viene chiamato tramite Memoize: foo_bar, la linea alias_method calci un prodotto dicendo errore non ha un metodo "nome" .. la mia comprensione è questo è perché alias_method tenterà di alias metodi di istanza non i metodi di classe .. (non so perché, ma ok non un grosso problema) ..

posso riaprire le eigenclass in questo modo

module Calculator 
    def memoize(name) 
    class << self 
     alias_method "memoized_#{name}", name 
    end 
    end 
end 

Questo potrebbe funzionare, ma il nome non è disponibile per il campo di applicazione la classe < < s definizione elfo. Le persone hanno menzionato l'uso di self.class_eval e self.instance_eval, ma nessuno di questi sembra funzionare .. Mi piacerebbe la mia torta e mangerla anch'io .. come posso mantenere alias_method dynamic ma usarlo su class_methods?

risposta

3

Quindi, appena saputo che questo farà il trucco:

module Calculator 
    def memoize 
    define_singleton_method(name, method(name)) 
    end 
end 

Poi, quando Calcolatrice viene incluso nel prodotto che verrà definire il metodo Singleton come avevo bisogno. Non so ancora perché alias_method abbia bisogno di lavorare solo sui metodi di istanza .. e non so perché class_eval o instance_eval non risolvono il problema .. ma almeno ho una soluzione ..

3

Cosa succede se hai messo il metodo di istanza per essere aliasizzato prima di includere/estendere? Se stai mettendo l'estensione subito dopo il nome della classe, il metodo di istanza non sarà stato ancora definito.

module Foo 
    def self.extended(base) 
    base.memoize :flavor 
    end 

    def memoize(name) 
    alias_method "memoized_#{name}", name 
    end 
end 

class Bar 
    def flavor 
    puts "Orange" 
    end 

    extend Foo 
end 

if __FILE__==$0 
    b = Bar.new 
    b.memoized_flavor #=> Orange 
end 
+0

Mentre un buon pensiero questo in realtà non era la situazione come il metodo che doveva essere alias è stato esteso nel modulo ed è stato esteso prima del tentativo di aliasing. Grande pensiero però. – Inc1982

Problemi correlati