2011-02-09 13 views
7

Tengo una clase en la que quiero poner métodos de fábrica para escupir una instancia nueva basada en uno de dos métodos de construcción: o puede construirse a partir de datos en memoria, o datos almacenados en un archivo.Iniciadores de instancias estáticas de clase (es decir, métodos de fábrica) en Ruby

Lo que me gustaría hacer es encapsular la lógica de cómo la construcción se lleva a cabo dentro de la clase, así que me gustaría disponer de métodos estáticos de clase que se establecen así:

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 

¿Hay ¿No hay forma de establecer @some_private_var en una instancia de una clase de la misma clase sin recurrir a la metaprogramación (instance_variable_set)? Parece que este patrón no es tan esotérico como para requerir variables de metapulsado en instancias. Realmente no tengo la intención de permitir que ninguna clase fuera de MyAppModel tenga acceso a some_published_var, por lo que no quiero usar, p. attr_accessor - parece que me falta algo ...

Respuesta

9

Quizás usar un constructor sea la mejor manera de lograr lo que quieres, simplemente hazlo protegido si no quieres crear instancias desde el "exterior"

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

Esto es muy agradable e idiomático. – Chuck

+0

Gracias, creo que esto es mucho más limpio que lo que estaba haciendo, todavía implica pasar un montón de cosas al constructor, pero como está protegido de todos modos, no es gran cosa, y mucho mejor que instance_variable_set. – Matt

Cuestiones relacionadas