Классические инициализаторы экземпляров (т.е. фабричные методы) в Ruby - PullRequest
7 голосов
/ 10 февраля 2011

У меня есть класс, в который я хочу поместить фабричные методы, чтобы выплевывать новый экземпляр на основе одного из двух методов конструирования: либо он может быть создан из данных в памяти, либо из данных, сохраненных в файле.

То, что я хотел бы сделать, это инкапсулировать логику того, как конструирование выполняется внутри класса, поэтому я хотел бы иметь статические методы класса, которые настроены следующим образом:

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

Есть линет способа установить @some_private_var для экземпляра класса из самого класса, не прибегая к метапрограммированию (instance_variable_set)?Кажется, что этот шаблон не настолько эзотеричен, чтобы требовать мета-ковыряющих переменных в экземплярах.Я действительно не собираюсь позволять любому классу вне MyAppModel иметь доступ к some_published_var, поэтому я не хочу использовать, например, attr_accessor - мне просто кажется, что я что-то упустил ...

1 Ответ

9 голосов
/ 10 февраля 2011

Может быть, использование конструктора - лучший способ достичь того, чего вы хотите, просто сделайте его защищенным, если вы не хотите создавать экземпляры "извне"

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
...