6

使用哈希定义的访问器方法动态创建对象的最简单方法是什么?例如,如果我有一个哈希:

{foo: "Foo", bar: "Bar"}

我想要一个对象,它分别具有访问器方法foofoo=barbar=初始值"Foo"、 和"Bar"。我可以想到做:

module ObjectWithAccessor
  def self.new h; Struct.new(*h.keys).new(*h.values) end
end

o = ObjectWithAccessor.new(foo: "Foo", bar: "Bar")
o.foo # => "Foo"

但是,我不需要它们的多个实例具有相同的特定键集,而是希望每次都使用可能不同的键集创建它的新实例,因此Struct每次为每个对象创建一个新类似乎矫枉过正,我想避免这种情况。有一个更好的方法吗?

4

1 回答 1

13

OpenStruct已经提供了你想要的:

require 'ostruct'

o = OpenStruct.new foo: "Foo", bar: "Bar"
o.foo  #=> "Foo"
o.bar  #=> "Bar"
o.bar = 'BAR'
o.bar  #=> "BAR"

或者,如果您不想在创建对象后定义任意属性(就像您可以使用 一样OpenStruct,您可以执行以下操作:

class ObjectWithAccessor
  def initialize attrs
    attrs.each do |name, val|
      singleton_class.send :attr_accessor, name.to_sym
      public_send :"#{name}=", val
    end
  end
end

o = ObjectWithAccessor.new foo: "Foo", bar: "Bar"
o.foo           #=> "Foo"
o.bar           #=> "Bar"
o.bar = 'BAR'
o.bar           #=> "BAR"
o.bsr = 'typo'  #=> #<NoMethodError: undefined method `bsr=' for #<Object:0x007fa4160847f8>>

这仍然不会创建一个只使用一次的新类,并且避免了OpenStruct.

于 2013-02-09T17:04:15.080 回答