如何猴子补丁“ GC.start”

问题描述 投票:1回答:1

我想做一些涉及到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

ruby memory garbage-collection metaprogramming monkeypatching
1个回答
2
投票

让我们重新定义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。使用Module#prepend的单例课程中的GC

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, ...] 

Module#prepend的单身人士类别中使用GC类似于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中首次亮相之前是常用的。

© www.soinside.com 2019 - 2024. All rights reserved.