2013-07-17 102 views
0

創建通用的構造,我發現這個有趣的答案:紅寶石

https://stackoverflow.com/a/2348854/169277

這是確定的,當你試圖把它真正偉大的作品實例變量。

有沒有采用同樣的邏輯或更好的一個來創建通用的構造類似的方式:

def initialize(obj) 
    obj.each do |k,v| 
    #find the setter for each k and set the value v to and return newly created object 
    end 
end 

如果我有對象TestObject

class TestObject 
attr_accessor :name, :surname, :sex 
end 

我想創建它像這個:

TestObject.new({:name => 'Joe', :surname => 'Satriani'}) 

如何實現這一目標?

這樣算下來,這將是一個速記:

t = TestObject.new 
t.name = 'Joe' 
t.surname = 'Satriani' 

回答

1

當然,你可以使用send任意消息發送到一個對象。由於我們在這裏操作self,因此我們可以直接調用send

def initialize(obj) 
    obj.each do |k,v| 
    send(:"#{k}=", v) 
    end 
end 

例如,TestObject.new({:name => 'Joe'})將調用send "name=", "Joe"

+0

你錯過了每個(我編輯)後,否則回答我在找什麼。謝謝 –

+0

對不起,我只是複製了最初的問題。 :) –

+0

好點謝謝,這是很容易判斷其他人哈哈 –

1

您可以從結構繼承做一個簡單的對象,然後通過在屬性初始化:

class TestObject < Struct.new(:name, :surname, :sex) 
end 

TestObject.new('Joe', 'Satriani') #=> sex will be nil 

您可以使用OpenStruct做出快速的值對象任意屬性:

t = OpenStruct(name: 'Joe', surname: 'Satriani') 

您可以包含一個模塊,如Virtus:https://github.com/solnic/virtus

或者你可以做Chris Heald說的。

0

我認爲使用關鍵字參數會更好。畢竟,Hash鍵保證是有效的Ruby標識符Symbol,因爲它們需要與方法名稱匹配。您不需要傳遞任何Ruby對象作爲Hash的鍵的功能。

def initialize(**attrs) 
    attrs.each do |attr, value| send(:"#{attr}=", value) end 
end 

TestObject.new(name: 'Joe', surname: 'Satriani') 
+0

我很熟悉'* attrs',但它意味着什麼'** attrs'? –

+0

@Priti:對於關鍵字參數是一樣的。它將所有多餘的關鍵字參數收集到一個'Hash'中,就像'*'將所有多餘的位置參數收集到'Array'中一樣。 –

+0

感謝您的時間和解釋... –