有没有办法在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”。
有什么想法吗?
答案 0 :(得分:4)
不,你不能直接这样做。最好的方法是只通过getter / setter方法访问实例变量并覆盖它们。
答案 1 :(得分:1)
您可以使用instance_variable_get,instance_variable_set和instance_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