【问题标题】:Creating an object on the fly with accessor methods使用访问器方法动态创建对象
【发布时间】:2013-02-09 16:56:22
【问题描述】:

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

{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"

但是,我不需要它们的多个实例具有相同的特定键集,而是希望每次都使用可能不同的键集创建它的新实例,因此使用 @987654329 创建一个新类@ 每次对每个对象似乎都过分了,我想避免这种情况。有没有更好的方法来做到这一点?

【问题讨论】:

    标签: ruby accessor


    【解决方案1】:

    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的“开放性”。

    【讨论】:

    • 请注意,OpenStruct 是“开放的”,如果更新现有属性,您可以通过拼写错误创建新属性。
    • @Phrogz 好点。我添加了不允许这样做的代码(因为它可能不需要),同时仍然避免创建只使用一次的类。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-26
    • 1970-01-01
    • 2020-05-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多