每次某个变量的值发生变化时,是否在ruby中有一个钩子?
答案 0 :(得分:3)
如果为Ruby编写C扩展,实际上可以创建一个全局变量,只要有人设置它就会触发setter钩子。
但是你可能不想这样做,因为你必须写一些C并且管理它可能会很痛苦。
更好的策略是使其变为通过适当的方法读取和设置变量。然后,当调用setter方法时,您可以执行任何操作。下面是一个将变量封装在对象中的示例:
class Foo
def bar=(v)
@bar = v
# do some stuff
end
def bar
@bar
end
end
类似地,您可以将变量封装在模块或类中而不是对象中。
答案 1 :(得分:1)
序言:我这不是一个解决方案(已经写过:没有),但也许它可以在特殊情况下提供帮助。
我的第一个想法是使用freeze
来获得解决方案:
a = "aa"
a.freeze
a << 'b' #can't modify frozen string (RuntimeError)
现在我们必须重新定义freeze
并在变量更改值时得到提示:
module FreezeWarning
def freeze
puts "#{self}: I am changed"
end
end
a = "aa"
a.extend(FreezeWarning)
a.freeze
a << 'b' #aa: I am changed
第一个问题:There is no way to get the variable name。
您可以使用附加变量解决此问题(您可以定义自己的变量标识,但不能是名称)
module FreezeWarning
def change_warning(name)
@varname = name
self.freeze
end
def freeze
puts "<#{@varname}> (#{self}): I am changed"
end
end
a = "aa"
a.extend(FreezeWarning)
a.change_warning('a')
a << 'b' #<a> (aa): I am changed
但更大的问题:这只适用于价值的变化,而不适用于新的分配:
a = 5
a.freeze
a = 4
p a # -> 4
所以这只是一个非常有限的“解决方案”。