Есть ли способ инициализировать объект через хэш?
Если у меня есть этот класс:
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)
который должен вызывать инициализацию каждой переменной экземпляра той, которая имеет то же имя в хеше.
Ответы
Ответ 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)
Но обратите внимание на подразумеваемое предупреждение в документации:
Устанавливает имена переменных экземпляра по символу для объекта, тем самым расстраивая попытки автора классов попытаться обеспечить правильную инкапсуляцию. Переменная не должна существовать до этого вызова.