2009-09-26 13 views
5

Diciamo che ho una classe Singleton come questo:Come aggiungere metodi della classe convenienza ad una classe Singleton in rubino

class Settings 
    include Singleton 

    def timeout 
    # lazy-load timeout from config file, or whatever 
    end 
end 

Ora, se voglio sapere cosa timeout da usare ho bisogno di scrivere qualcosa di simile:

Settings.instance.timeout 

ma preferirei che accorciare a

Settings.timeout 

Un modo ovvio per fare questo lavoro sarebbe quello di modificare l'Imple mentazione di impostazioni per:

class Settings 
    include Singleton 

    def self.timeout 
    instance.timeout 
    end 

    def timeout 
    # lazy-load timeout from config file, or whatever 
    end 
end 

che funziona, ma sarebbe piuttosto noioso scrivere manualmente un metodo di classe per ciascun metodo di istanza. Questo è rubino, ci deve essere un modo intelligente intelligente per farlo.

risposta

10

Un modo per farlo è come questo:

require 'singleton' 
class Settings 
    include Singleton 

    # All instance methods will be added as class methods 
    def self.method_added(name) 
    instance_eval %Q{ 
     def #{name} 
     instance.send '#{name}' 
     end 
    } 
    end 


    def timeout 
    # lazy-load timeout from config file, or whatever 
    end 
end 

Settings.instance.timeout 
Settings.timeout 

Se si vuole più controllo a grana fine su quali metodi di delegare, quindi è possibile utilizzare le tecniche di delega:

require 'singleton' 
require 'forwardable' 
class Settings 
    include Singleton 
    extend SingleForwardable 

    # More fine grained control on specifying what methods exactly 
    # to be class methods 
    def_delegators :instance,:timeout,:foo#, other methods 

    def timeout 
    # lazy-load timeout from config file, or whatever 
    end 

    def foo 
    # some other stuff 
    end 

end 

Settings.timeout 

Settings.foo 

D'altra lato, raccomando di utilizzare i moduli se la funzionalità prevista è limitata al comportamento, tale soluzione sarebbe:

module Settings 
    extend self 

    def timeout 
    # lazy-load timeout from config file, or whatever 
    end 

end 

Settings.timeout 
+1

Impressionante risposta. Nel mio caso specifico, SingleForwardable è esattamente quello che stavo cercando. Grazie! –

Problemi correlati