2012-05-09 25 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