2011-02-09 19 views
7

Mam klasę, którą chcę wprowadzić metody fabryczne, aby wypluć nową instancję opartą na jednej z dwóch metod konstrukcyjnych: albo można ją zbudować z danych w pamięci, lub dane przechowywane w pliku.Inicjatory instancji klasy statycznej (tj. Metody fabryczne) w Rubim

Co chciałbym zrobić to ująć logikę jak budowa odbywa się wewnątrz klasy, więc chciałbym mieć statyczne metody klasy, które są ustawione tak:

class MyAppModel 
    def initialize 
     #Absolutely nothing here - instances are not constructed externally with MyAppModel.new 
    end 

    def self.construct_from_some_other_object otherObject 
     inst = MyAppModel.new 
     inst.instance_variable_set("@some_non_published_var", otherObject.foo) 
     return inst 
    end 

    def self.construct_from_file file 
     inst = MyAppModel.new 
     inst.instance_variable_set("@some_non_published_var", get_it_from_file(file)) 
     return inst 
    end 
end 

Czy istnieje nie ma możliwości ustawienia @some_private_var na instancję klasy z samej klasy bez odwoływania się do metaprogramowania (instance_variable_set)? Wygląda na to, że ten wzorzec nie jest tak ezoteryczny, aby wymagać zmiennych meta-pokingowych w instancjach. Naprawdę nie zamierzam pozwolić żadnej klasie spoza MyAppModel mieć dostępu do some_published_var, więc nie chcę używać np. attr_accessor - po prostu czuję, że czegoś brakuje ...

Odpowiedz

9

Być może użycie konstruktora jest lepszym sposobem na osiągnięcie tego, co chcesz, po prostu uczyń go chronionym, jeśli nie chcesz tworzyć instancji z "zewnątrz"

class MyAppModel 
    class << self 
    # ensure that your constructor can't be called from the outside 
    protected :new 

    def construct_from_some_other_object(other_object) 
     new(other_object.foo) 
    end 

    def construct_from_file(file) 
     new(get_it_from_file(file)) 
    end 
    end 

    def initialize(my_var) 
    @my_var = my_var 
    end 
end 
+1

To jest bardzo ładne i idiomatyczne. – Chuck

+0

Dzięki, myślę, że jest to znacznie czystsze niż to, co robiłem - nadal wiąże się z przekazywaniem kilku rzeczy do konstruktora, ale ponieważ jest to chronione, to nic wielkiego - i znacznie lepiej niż instance_variable_set. – Matt

Powiązane problemy