Dan*_*Tao 5 ruby metaprogramming alias-method
假设我有一段Ruby代码,我想在其中添加一个方法(我不知道为什么;让我假设我有充分的理由).
class String
alias_method :contains?, :include?
end
Run Code Online (Sandbox Code Playgroud)
在本节之后,我可以删除这个别名吗?
remove_method应该在大多数情况下工作.但如果您alias_method覆盖现有方法,则可能需要通过单独的alias_method调用保存原始方法.
# assuming :contains? is already a method
alias_method :original_contains?, :contains?
alias_method :contains?, :include?
Run Code Online (Sandbox Code Playgroud)
然后恢复原始状态:
alias_method :contains?, :original_contains?
remove_method :original_contains? # optional
Run Code Online (Sandbox Code Playgroud)
另请注意,修改在多个线程中使用的类很容易出现竞争条件.如果你试图禁止libs使用别名,你就无法阻止,如果你在别名存在时调用那些libs的方法.我们可能会在ruby 2.0中看到一种方法:http://yehudakatz.com/2010/11/30/ruby-2-0-refinements-in-practice/
如果您可以说出要删除别名的原因,将会很有帮助.如果以前没有方法名称,那么猴子补丁不会影响其他库.此外,您应该考虑子类化String(或委托给字符串实例)而不是修补String.
def hello
puts "Hello World"
end
alias :hi :hello
hi #=> "Hello World"
undef hi
hi #=> NameError
hello #=> "Hello World"
Run Code Online (Sandbox Code Playgroud)
编辑:请注意,这仅适用于在main对象上创建的方法。为了在课堂上实现这一点,你需要做类似的事情,Hello.class_eval("undef hi")
然而,从元编程的角度来看,在处理类时,我喜欢使用 ,remove_method :hi因为它会导致方法查找失败并从父类中获取方法。
class Nums < Array
def include?
puts "Just Kidding"
end
end
n = Nums.new
n << 4 #=> [4]
n.include? #=> "Just kidding"
Nums.class_eval("remove_method :include?")
n.include? 4 #=> true
Number.class_eval("undef include?")
n.include? 4 #=> NoMethodError
Run Code Online (Sandbox Code Playgroud)
remove_method对元更加友好。
| 归档时间: |
|
| 查看次数: |
1912 次 |
| 最近记录: |