有没有办法通过哈希初始化对象?

Geo*_*Geo 37 ruby hash constructor initialization

如果我有这个课程:

class A
  attr_accessor :b,:c,:d
end
Run Code Online (Sandbox Code Playgroud)

而这段代码:

a = A.new
h = {"b"=>10,"c"=>20,"d"=>30}
Run Code Online (Sandbox Code Playgroud)

是否可以直接从哈希初始化对象,而不需要遍历每一对并调用instance_variable_set?就像是:

a = A.new(h)
Run Code Online (Sandbox Code Playgroud)

这应该导致每个实例变量初始化为散列中具有相同名称的变量.

jrh*_*cks 51

您可以在类上定义初始化函数:

class A
  attr_accessor :b,:c,:d
  def initialize(h)
    h.each {|k,v| public_send("#{k}=",v)}
  end
end
Run Code Online (Sandbox Code Playgroud)

或者你可以创建一个模块,然后"混合进去"

module HashConstructed
 def initialize(h)
  h.each {|k,v| public_send("#{k}=",v)}
 end
end

class Foo
 include HashConstructed
 attr_accessor :foo, :bar
end
Run Code Online (Sandbox Code Playgroud)

或者你可以尝试类似构造函数的东西

  • +1.顺便说一下,您可能要考虑使用`public_send`而不是`send`来避免调用私有属性编写者:) (3认同)

ste*_*lag 15

OpenStruct值得考虑:

require 'ostruct' # stdlib, no download
the_hash = {"b"=>10, "c"=>20, "d"=>30}
there_you_go = OpenStruct.new(the_hash)
p there_you_go.c #=> 20
Run Code Online (Sandbox Code Playgroud)

  • 是的!而且你还可以将 JSON 转换为 OpenStruct,这很好。`JSON.parse({a: 1, b: 2}.to_json, object_class: OpenStruct)` (2认同)

klo*_*ner 10

instance_variable_set 适用于此类用例:

class A
  def initialize(h)
    h.each {|k,v| instance_variable_set("@#{k}",v)}
  end
end
Run Code Online (Sandbox Code Playgroud)

这是一个公共方法,所以你也可以在构建后调用它:

a = A.new({})
a.instance_variable_set(:@foo,1)
Run Code Online (Sandbox Code Playgroud)

但请注意文档中隐含的警告:

将符号的实例变量名称设置为object,从而使类的作者尝试提供适当的封装的努力受挫.在此调用之前,变量不必存在.

  • 对我而言,确保您只能设置定义中指定的设置的检查非常重要,这使该建议不值得 (2认同)