在Ruby中使用哈希作为工厂

时间:2015-08-17 20:01:40

标签: ruby methods hash factory

我想使用哈希来实例化某种类型的对象,但是问题很快就会出现,因为哈希只会实例化一个实例,然后永远会指向'那个例子。

class Person
end

factory = { "make_person" => Person.new }

a = factory["make_person"]
b = factory["make_person"]

a == b
=> true

即使哈希指向一个方法,例如make_person,它调用它内部Person.new,它仍将永远指向一个实例。

有人有解决方法吗?非常感谢。

4 个答案:

答案 0 :(得分:4)

正在将对象( /** * @Route("/logout") */ public function logoutAction() { $this->get('security.token_storage')->setToken(null); $this->get('request')->getSession()->invalidate(); //if this works how do I redirect to another route, //specifically back to /login return $this->render( //do i need a template? //do i need the array here? ); } 的实例)分配给" make_person"键。

每当您要求Person键时,您都会获得该对象。

您需要使用lambda初始化"make_person"懒惰。

Person

答案 1 :(得分:2)

正确答案是哈希是错误的用法。

为什么不使用普通的Ruby类?

class Factory
  def self.[](type)
    case type
    when "make_person"
      Person.new
    when "make_other_thing"
      # ...
    end
  end
end

a = Factory["make_person"]
b = Factory["make_person"]
a == b # => false

如果你想得到一点点发烧友:

class Factory
  class << self
    def [](type)
      return send(type) if respond_to?(type)
      raise "I don't know how to do `#{type}'!"
    end

    def make_person
      Person.new
    end

    def make_other_thing
      # ...
    end
  end
end

...但是你可以调用Factory.make_person,因此[]方法似乎是多余的。

如果你真的,真的想要使用Hash来获取没有理由使用Hash的东西,你可以这样做:

factory = {
  "make_person" => -> { Person.new }
}

a = factory["make_person"][]
b = factory["make_person"][]
a == b # => false

或者这个:

factory = Hash.new do |_, key|
  case key
  when "make_person"
    Person.new
  when "make_other_thing"
    # ...
  end
}

a = factory["make_person"]
b = factory["make_person"]
a == b # => false

答案 2 :(得分:0)

您引用了Person的同一个实例,而不是Person的一些新实例。

让我们挖掘一下:

[3] pry(main)> factory = {}
=> {}
[4] pry(main)> factory.object_id
=> 70344866826960
[5] pry(main)> class Person
[5] pry(main)* end
=> nil
[6] pry(main)> factory["make_person"] = Person.new
=> #<Person:0x007ff4e4136038>

人被实例化,让我们检查它的object_id:

[7] pry(main)> factory["make_person"].object_id
=> 70344887611420

让我们将它分配给变量a:

[8] pry(main)> a = factory["make_person"]
=> #<Person:0x007ff4e4136038>

让我们将它分配给变量b:

[9] pry(main)> b = factory["make_person"]
=> #<Person:0x007ff4e4136038>

现在既是&amp; b指向object_id

所示的同一对象
[10] pry(main)> a.object_id
=> 70344887611420
[11] pry(main)> b.object_id
=> 70344887611420

正如克里斯所指出的那样,有几种方法可以让你的行为得以实现,但上述内容对你来说非常重要。

每次拨打factory["make_person"]时如何确保新人员实例化的示例:

factory["make_person"] = lambda { Person.new }.call
=> #<Person:0x007ff4e0fa6ba8>

答案 3 :(得分:0)

不知道为什么你希望它成为哈希。但如果你坚持,我们走了:

factory = Hash.new do |_, key|
  blueprints = { "make_person" => Person }
  blueprints[key].new
end

person_x = factory["make_person"]
person_y = factory["make_person"]

person_x.object_id == person_y.object_id # => false