开发者

Is there a way to initialize an object through a hash?

开发者 https://www.devze.com 2022-12-08 09:18 出处:网络
If I have this class: class A attr_accessor :b,:c,:d end and this code: a = A.new h = {\"b\"=>10,\"c\"=>20,\"d\"=>30}

If I have this class:

class A
  attr_accessor :b,:c,:d
end

and this code:

a = A.new
h = {"b"=>10,"c"=>20,"d"=>30}

is it possible to initialize the object directly from the hash, without me needing to go over each pair and call instance_variable_set? Something like:

开发者_StackOverflow
a = A.new(h)

which should cause each instance variable to be initialized to the one that has the same name in the hash.


You can define an initialize function on your class:

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

Or you can create a module and then "mix it in"

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

class Foo
 include HashConstructed
 attr_accessor :foo, :bar
end

Alternatively you can try something like constructor


OpenStructis worth considering:

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


instance_variable_set is intended for this kind of use case:

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

It's a public method, so you could also call it after construction:

a = A.new({})
a.instance_variable_set(:@foo,1)

But note the implied warning in the documentation:

Sets the instance variable names by symbol to object, thereby frustrating the efforts of the class’s author to attempt to provide proper encapsulation. The variable did not have to exist prior to this call.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号