Ruby访问魔法

时间:2010-01-21 12:01:38

标签: ruby singleton

假设我有以下课程:

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

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

5 个答案:

答案 0 :(得分: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"

答案 1 :(得分:1)

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

这可能与插件weppos所讨论的方法相同。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

您可以使用instance_varibable_set和instance_variable_get:

执行此操作

MyClass.instance_variable_set(:@ var_name,“value”)

答案 4 :(得分: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