如何 monkeypatch "GC.start"
How to monkeypatch "GC.start"
我想做一些涉及挂钩 GC.start
调用的实验。
Ruby 告诉我 GC
不是 class 当我 运行 这个:
class GC
def self.start
puts "hello"
super
end
end
但是 运行 宁这个,Ruby 告诉我 GC.start
没有超级 class,所以我想我实际上并没有连接到原来的那个,但是只是以某种方式接管了那个名字:
module GC
def self.start
puts "hello"
super
end
end
GC.start
如何使用 monkeypatch GC.start
?
我们先重新定义 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
的单例 class
中使用 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
的单例 class 中使用 Module#prepend
类似于 GC.extend X
除了它把 X
放在 GC
的单例之前class 在 GC
的祖先中。另见 Method#super_method, Object#method, Kernel#__method__ and 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 中首次亮相之前很常用。
我想做一些涉及挂钩 GC.start
调用的实验。
Ruby 告诉我 GC
不是 class 当我 运行 这个:
class GC
def self.start
puts "hello"
super
end
end
但是 运行 宁这个,Ruby 告诉我 GC.start
没有超级 class,所以我想我实际上并没有连接到原来的那个,但是只是以某种方式接管了那个名字:
module GC
def self.start
puts "hello"
super
end
end
GC.start
如何使用 monkeypatch GC.start
?
我们先重新定义 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
的单例 class
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
的单例 class 中使用 Module#prepend
类似于 GC.extend X
除了它把 X
放在 GC
的单例之前class 在 GC
的祖先中。另见 Method#super_method, Object#method, Kernel#__method__ and 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 中首次亮相之前很常用。