2010-01-21 131 views
1

假设,我有下面的类:红宝石访问魔术

class MyClass 
    attr_accessor :vars 

    def initialize 
    @vars = [] 
    end 

    def add_var var 
    @vars << var 
    end 

end 

我要访问内部件瓦尔这样的:

x = MyClass.new('root') 
x.add_var 'test' 
x.add_var 'something' 
x.add_var Myclass.new('google') 
x.google.add_var 'nice' 

puts x.test 
puts x.something 
puts x.google.nice 

一般来说,这可能吗?我应该在哪里挖掘?

+1

你可以随时去'method_missing'方式。 – vava 2010-01-21 12:11:19

+1

另外,看看OpenStruct(http://www.ruby-doc.org/core/classes/OpenStruct.html),不是真的你想要的语法,但基本上是相同的。 – vava 2010-01-21 12:16:53

回答

4

这是标准Ruby库的一部分,它被称为OpenStruct:

#!/usr/bin/ruby1.8 

require 'ostruct' 

x = OpenStruct.new 
x.google = OpenStruct.new 
x.google.nice = 'Nice. Real nice' 
p x.google.nice  # "Nice. Real nice" 

您还可以在构造函数初始化属性:

x = OpenStruct.new(:google=>OpenStruct.new(:nice=>'Nice. Real nice')) 
p x.google.nice # => "Nice. Real nice" 
0

当然可以。对于应用程序范围的配置设置,这正是例如this plugin does

1

如果你想自己实现这样的东西,你应该找到更多关于method_missing。当找不到方法时调用此方法。使用一些聪明的代码在你的@vars中找到被调用的方法名称并对此做出反应。

这可能与插件weppos所使用的方法相同。

MyClass.instance_variable_set:

0

你可以instance_varibable_set和instance_variable_get做到这一点(:@ VAR_NAME, “值”)

0

就动态地定义了一种新方法,并使其返回所需的对象:

class MyClass 
    attr_accessor :vars 
    attr_reader :name 

    def initialize(name) 
     @name = name 
     @vars = [] 
    end 

    def add_var(var) 
     @vars << var 

     if var.instance_of?(MyClass) 
      class << self; self; end.send(:define_method, var.name.to_sym) { 
       var 
      } 
     end 
    end 
end 

x = MyClass.new(:x) 
x.add_var MyClass.new(:google) 
x.google.add_var MyClass.new(:nice) 
x.google.nice.name #=> :nice 
+0

定义新方法是一件棘手的事情。假设OP的例子是对现实的简单观点,事情可能会变得混乱。 – Veger 2010-01-21 12:31:21

+0

我也认为'method_missing'可能是一个痛苦,尤其是。因为强大的实现需要修补'respond_to?'。 – horseyguy 2010-01-21 12:53:55

+0

确实如此,但它在删除,重命名等变量中似乎更加灵活,因为它直接依赖于@vars。因此,它的任何变化都会立即反映出来。 – Veger 2010-01-21 12:59:29