当变量改变时调用Hook

时间:2012-01-14 05:53:21

标签: ruby variables

每次某个变量的值发生变化时,是否在ruby中有一个钩子?

2 个答案:

答案 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

所以这只是一个非常有限的“解决方案”。