2009-10-15 91 views
35

如果我有這個類:有沒有辦法通過哈希來初始化一個對象?

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) 

這應該引起每個實例變量初始化爲具有哈希同名的人。

回答

50

您可以在類中定義的初始化函數:

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

+3

+1。順便說一句,你可能要考慮使用'public_send'而不是'send'來避免調用私有屬性編寫器:) – epidemian 2014-02-21 18:48:20

+1

+ 1爲構造函數gem – 2014-07-23 15:47:00

8

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) 

但要注意在documentation隱含警告:

由符號設置實例變量名對象,因此挫敗了班級作者試圖提供適當封裝的努力。此調用之前,變量不必存在。

+1

對我來說,檢查以確保你只能設置定義中指定的那些重要的是,這使得這個建議不值得。 – 2013-10-17 04:45:52

10

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 
+1

是的!你也可以將JSON轉換成OpenStruct,這很好。 'JSON.parse({a:1,b:2} .to_json,object_class:OpenStruct)' – 2015-08-10 03:27:14

相關問題