2009-09-26 18 views
5

Powiedzmy mam singleton klasy tak:Jak dodać metod klasy wygoda do klasy Singleton w Ruby

class Settings 
    include Singleton 

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

Teraz jeśli chcę wiedzieć, co czas oczekiwania używać muszę napisać coś takiego:

Settings.instance.timeout 

ale wolałbym skrócić że do

Settings.timeout 

jeden oczywisty sposób do tej pracy byłoby zmodyfikować wyko żania ustawienia do:

class Settings 
    include Singleton 

    def self.timeout 
    instance.timeout 
    end 

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

to działa, ale to byłoby dość uciążliwe ręcznie napisać metodę klasy dla każdej metody instancji. To jest rubin, musi to być mądry i sprytny, dynamiczny sposób, aby to zrobić.

Odpowiedz

10

Jednym ze sposobów na to jest tak:

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 

Jeśli chcesz bardziej drobnoziarnista kontrolę na której metody delegowania, a następnie można użyć technik delegacji:

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 

Z drugiej strony po stronie, polecam używanie modułów, jeśli zamierzona funkcjonalność jest ograniczona do zachowania, takie rozwiązanie byłoby:

module Settings 
    extend self 

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

end 

Settings.timeout 
+1

Awesome odpowiedź. W moim konkretnym przypadku SingleForwardable jest dokładnie tym, czego szukałem. Dzięki! –

Powiązane problemy