2012-05-09 53 views
3

如何將一堆實例變量從一個對象添加到另一個對象?Ruby:將實例變量添加到對象

例如,想象您擁有基礎機器人的機器人,您可以使用附加軟件對其進行自定義。

 
class Robot 

    def initialize 
     @name = "simple robot" 
     @power = nil #no power 
     @speed = nil 
     # more attributes 
    end 

    def add_attributes(addon) 
     @power = addon.power 
     @speed = addon.speed 
     #the rest of the attributes that addon has 
    end 
end 

我想重新寫add_attributes方法簡單地遍歷每個插件的屬性,而不是寫他們都一個接一個的,原因可能有幾十個屬性。

一些插件可能有Robot沒有的實例變量,我也想將它們添加到Robot中。就像在飛行中創建實例變量一樣?

回答

7

這取決於你的意思是「屬性」; Ruby沒有這個概念直接,但你可以從一個對象複製實例變量到另一個這樣的:

def add_attributes(addon) 
    addon.instance_variables.each do |x| 
    self.instance_variable_set(addon.instance_variable_get(x)) 
    end  
end 

[編輯]注意,answer by @HolgerJust也是一個很好的解決方案。

+0

我真的不喜歡窺視到附加的實例變量是這樣的。一個插件應該提供一個統一的方式來獲取它的屬性列表,然後可以調用該方法。 (當然,對於給定的信息,你有什麼可能是最好的解決方案。) –

5

您可以擺脫實例變量並改爲使用單個散列。這具有免費枚舉器和乾淨的界面的優點,可以從一個方便的地方訪問機器人的所有功能。

它也避免了必須弄亂實例內部變量。它們通常用於內部並用於大量的內容。如果你想公開功能,你應該使用公開的方法。與內部狀態混淆至少是糟糕的設計,並且很可能會在以後導致很多悲傷。一般來說,儘可能避免元編程是最好的。

class Robot 
    attr_reader :features 

    def initialize 
    @features = {} 
    @features[:name] = "simple robot" 
    @features[:power] = nil #no power 
    @features[:speed] = nil 
    end 

    def add_attributes(addon) 
    @features.merge! addon.features 
    end 
end 
+1

使用[哈希#合併](http://www.ruby-doc.org/core-1.9.3/Hash.html#method -i-merge)而不是遍歷'addon'參數將清理'add_attributes'方法。 – Cade

+0

@Cade:當然。編輯。 –

+0

+1是的,這可能是更好的解決方案。 – maerics

0

您可以使用靈活的gem [0],它允許您在不需要編寫大量代碼的情況下即時創建實例變量。 只是做

class SomeClass 
    include Flexible 
end 
sc = SomeClass.new 
sc.my_variable_name = 1 # or any other value 

[0] https://github.com/matthiasbeyer/flexible