如何知道在Ruby中设置实例变量的时间

时间:2010-04-18 02:39:24

标签: ruby

有没有办法在Ruby中覆盖实例变量的设置?

假设我设置了一个实例变量:

@foo = "bar"

我可以截取并执行某些操作(例如记录或放置)

我想,我试图覆盖所有类型的赋值运算符。甚至可以这样做吗?

到目前为止,我提出的最好的是:

class Module
  def attr_log_accessor( *symbols )
    symbols.each { | symbol |
      module_eval( "def #{symbol}() @#{symbol}; end" )
      module_eval( "def #{symbol}=(val) 
                      @#{symbol} = val
                      puts \"#{symbol} has changed\"
                    end" )
    }
  end
end

然后,当我定义访问器并设置它时,我的代码被执行:

class Test
  attr_log_accessor :foo

  def DoSomething
    self.foo = "bar"
  end
end

不幸的是,这需要我写self.foo =“bar”,而不是@foo =“bar”。

有什么想法吗?

3 个答案:

答案 0 :(得分:4)

不,你不能直接这样做。最好的方法是只通过getter / setter方法访问实例变量并覆盖它们。

答案 1 :(得分:1)

您可以使用instance_variable_getinstance_variable_setinstance_variables。在Ruby's Metaprogramming Toolbox这篇文章中可以找到更多内容。

如果您可以描述为什么要尝试这样做,我们可能会提供更好的方法。

答案 2 :(得分:0)

您可以使用method_missing()

执行此操作

示例:

def method_missing(name, *args)
  attribute = name.to_s
  if attribute =~ /=$/
    @attributes[attribute.chop] = args[0]
  else
    @attributes[attribute]
  end
end

如果你在getter / setter中进行处理,这种方法会很快变得臃肿。

有关更多信息,请查看OpenStruct源代码。另外,我从Metaprogramming Ruby(第52页)

中提取了此代码

另外,请注意,这将捕获所有缺少的方法。如果您只想截取obj.[*]=,则必须将@attributes[attribute]更改为super