Ruby是否提供了一个常量添加的钩子方法?

Ruby是否提供了一个常量添加的钩子方法?,ruby,hook,constants,Ruby,Hook,Constants,我知道Ruby提供了几种有用的钩子方法。然而,我似乎找不到任何类似于“常量”的钩子。我之所以想要一个,是因为我希望重写它,这样每当添加一个常量时,就可以执行某些其他操作来更新一些变量,而不必自己调用某种更新方法 更具体地说,我试图保留一个与特定正则表达式匹配的所有现有常量的列表,但不在所有现有常量上循环,以一定的间隔搜索匹配项,也不在最后添加的常量与正则表达式匹配时更新列表;我相信这需要一个显式的方法调用 如果一个钩子还不存在,是否可以创建一个钩子,如果不存在,我如何获得这个行为?我曾经在Rub

我知道Ruby提供了几种有用的钩子方法。然而,我似乎找不到任何类似于“
常量”的钩子。我之所以想要一个,是因为我希望重写它,这样每当添加一个常量时,就可以执行某些其他操作来更新一些变量,而不必自己调用某种更新方法

更具体地说,我试图保留一个与特定正则表达式匹配的所有现有常量的列表,但不在所有现有常量上循环,以一定的间隔搜索匹配项,也不在最后添加的常量与正则表达式匹配时更新列表;我相信这需要一个显式的方法调用


如果一个钩子还不存在,是否可以创建一个钩子,如果不存在,我如何获得这个行为?

我曾经在Ruby 1.9中使用
内核。set_trace\u func
实现过。您可以继续检查
“行”
事件。每当发生此类事件时,使用
常数
方法获取常数与前一次的差值。如果您检测到差异,那么这就是添加/删除常量的时刻

Kernel.set_trace_func ->event, _, _, _, _, _{
  case event
  when "line"
    some_routine
  end
}

Ruby 2.0可能有更强大的API,它允许一种更直接的方法来实现,但我不确定。

所以我想我已经想出了一个替代方案:

class Object
  def typedef &block
    Module.new &block
  end
end

module Type
  @@types = []
  @@prev = Module.constants

  def self.existing_types
    diff = Module.constants - @@prev
    @@prev = Module.constants

    new_types = diff.select { |const| const.to_s.start_with? 'TYPE_' }

    @@types |= new_types
  end
end
当我访问常量列表时,我处理它,而不是监视创建常量的时间。现在我可以这样做:

irb(main):002:0> Type.existing_types
=> []
irb(main):003:0> TYPE_rock = typedef do
irb(main):004:1*   def self.crumble
irb(main):005:2>     puts "I'm crumbling! D:"
irb(main):006:2>   end
irb(main):007:1> end
=> TYPE_rock
irb(main):008:0> Type.existing_types
=> [:TYPE_rock]
irb(main):009:0> FOO_CONST = 54
=> 54
irb(main):011:0> TYPE_water = typedef do
irb(main):012:1*   def self.splash
irb(main):013:2>     puts "Water! :3"
irb(main):014:2>   end
irb(main):015:1> end
=> TYPE_water
irb(main):016:0> Type.existing_types
=> [:TYPE_rock, :TYPE_water]
irb(main):017:0> TYPE_rock.crumble
I'm crumbling! D:
=> nil
irb(main):018:0> TYPE_water.splash
Water! :3
=> nil

你觉得怎么样?这就完成了我想要的,它相当简单,但我还是Ruby新手,我不确定Ruby是否已经提供了一些好的API来实现这一点。

Ruby 2.0提供了一个名为
Kernel::set_trace\u func
的面向对象API。这两件事都实现了我的目标,但我想知道性能的影响?当我在IRB中测试它时,当我激活跟踪功能时,在键入和评估时出现了非常明显的延迟。我想说,如果我需要监控特定的代码块以不断创建代码,这将是一个很好的解决方案,但如果钩子方法对性能影响如此之大,我认为这不是一个实用的替代方法,不幸的是:\
Kernel::set\u trace\u func
(或
TracePoint
)非常酷!当然,我可能不会每天都使用它,但是如果我需要它,知道它的存在是很有用的。如果你想跟踪类名,你可以连接到
class#inherited
,它将在每次定义类时被调用。您还可以连接到
Module#extended
Module#included
以跟踪模块的使用时间。否则,TracePoint就是你的朋友。它可能会实现你想要的,但并不能回答你原来的问题。你改变了问题。然而,这可能是个好主意。虽然我想我会选择我的替代方案,但如果人们对我最初的问题有什么建议,我仍然很感兴趣。我刚刚开始学习和使用Ruby,但我想好好学习和使用它。