Подтвердить что ты не робот

Есть ли способ инициализировать объект через хэш?

Если у меня есть этот класс:

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

и этот код:

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

Можно ли инициализировать объект непосредственно из хэша, без необходимости перебирать каждую пару и вызывать instance_variable_set? Что-то вроде:

a = A.new(h)

который должен вызывать инициализацию каждой переменной экземпляра той, которая имеет то же имя в хеше.

4b9b3361

Ответ 1

Вы можете определить функцию инициализации в своем классе:

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

Или вы можете создать модуль, а затем "соединить его в"

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

class Foo
 include HashConstructed
 attr_accessor :foo, :bar
end

В качестве альтернативы вы можете попробовать что-то вроде constructor

Ответ 2

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

Ответ 3

instance_variable_set предназначен для такого вида использования:

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

Это общедоступный метод, поэтому вы можете также назвать его после построения:

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

Но обратите внимание на подразумеваемое предупреждение в документации:

Устанавливает имена переменных экземпляра по символу для объекта, тем самым расстраивая попытки автора классов попытаться обеспечить правильную инкапсуляцию. Переменная не должна существовать до этого вызова.