【问题标题】:How to monkeypatch "GC.start"如何猴子补丁“GC.start”
【发布时间】:2020-05-24 03:15:17
【问题描述】:

我想做一些涉及挂钩到 GC.start 调用的实验。

当我运行这个时,Ruby 告诉我 GC 不是一个类:

class GC
  def self.start
    puts "hello"
    super
  end
end

但是运行这个,Ruby 告诉我 GC.start 没有超类,所以我认为我实际上并没有挂接到原来的那个,而是以某种方式接管了那个名字:

module GC
  def self.start
    puts "hello"
    super
  end
end
GC.start

我怎样才能猴子补丁GC.start

【问题讨论】:

  • GC 是一个模块,但是由于你对模块方法(而不是实例方法)感兴趣,所以你需要对GC 的单例类进行操作。

标签: ruby memory garbage-collection metaprogramming monkeypatching


【解决方案1】:

让我们首先重新定义GC::start,以便我们可以看到它何时被调用。

module GC
  def self.start(full_mark: true, immediate_sweep: true)
    puts "old start, full_mark: #{full_mark}, " +
      "immediate_sweep: #{immediate_sweep}"
  end
end  

这里有两种方法可以得到想要的结果。

1.在GC 的单例类中使用Module#prepend

module X 
  def start(full_mark: true, immediate_sweep: true)
    puts "new start, full_mark: #{full_mark}, " +
      "immediate_sweep: #{immediate_sweep}"
    method(__method__).super_method.call(full_mark: full_mark,
      immediate_sweep: immediate_sweep)  
  end
end

module GC
  class << self
    prepend X
  end
end

GC.start(full_mark: 'cat')
new start, full_mark: cat, immediate_sweep: true
old start, full_mark: cat, immediate_sweep: true

注意:

GC.singleton_class.ancestors
  #=> [X, #<Class:GC>, Module, ...] 

GC 的单例类中使用Module#prepend 类似于GC.extend X,只是它将X 放在GC 的单例类之前GC 的祖先。另请参阅Method#super_methodObject#methodKernel#__method__Method#call

还要注意:

GC.singleton_class.public_send(:prepend, X)

可以用来代替:

module GC
  class << self
    prepend X
  end
end

2。使用别名

module GC
  class << self
    alias old_start start
  end

  def self.start(full_mark: true, immediate_sweep: true)
    puts "new start, full_mark: #{full_mark}, " +
      "immediate_sweep: #{immediate_sweep}"
    old_start(full_mark: full_mark, immediate_sweep: immediate_sweep)
  end
end

GC.start(full_mark: 'cat')
new start, full_mark: cat, immediate_sweep: true
old start, full_mark: cat, immediate_sweep: true

Module#prepend 在 Ruby v2.0 中首次亮相之前,通常使用别名。

【讨论】:

    猜你喜欢
    • 2011-10-06
    • 2016-09-01
    • 2012-09-16
    • 2012-12-18
    • 2020-01-09
    • 1970-01-01
    • 1970-01-01
    • 2010-09-29
    • 2021-04-04
    相关资源
    最近更新 更多