6

ハッシュによって定義されたアクセサ メソッドを使用してオンザフライでオブジェクトを作成する最も簡単な方法は何ですか? たとえば、ハッシュがある場合:

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

fooアクセサ メソッド、foo=bar、およびbar=初期値"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 に答える