【问题标题】:Can I remove a method alias in Ruby?我可以在 Ruby 中删除方法别名吗?
【发布时间】:2012-07-12 17:20:33
【问题描述】:

假设我有一段 Ruby 代码我想为一个方法设置别名(我不知道为什么;假设我有充分的理由)。

class String
    alias_method :contains?, :include?
end

在本节之后,我可以删除这个别名吗?

【问题讨论】:

    标签: ruby metaprogramming alias-method


    【解决方案1】:

    remove_method 在大多数情况下应该可以工作。但如果您的 alias_method 覆盖了现有方法,您可能需要通过单独的 alias_method 调用来保存原始方法。

    # assuming :contains? is already a method 
    alias_method :original_contains?, :contains?
    alias_method :contains?, :include?
    

    然后恢复原来的状态:

    alias_method :contains?, :original_contains?
    remove_method :original_contains?  # optional
    

    还要注意,修改在多个线程中使用的类很容易出现竞争条件。如果您试图禁止库使用别名,那么如果您在别名存在时调用这些库的方法,则无法阻止这种情况。我们可能会在 ruby​​ 2.0 中看到一种方法:http://yehudakatz.com/2010/11/30/ruby-2-0-refinements-in-practice/

    如果您能说出您想要删除别名的原因,将会很有帮助。如果该方法名称之前不存在,则其他库不应受到猴子补丁的影响。此外,您应该考虑继承 String(或委托给字符串实例)而不是修补 String。

    【讨论】:

    • 谢谢,很棒的提示!
    【解决方案2】:
    def hello
       puts "Hello World"
    end
    alias :hi :hello
    
    hi #=> "Hello World"
    undef hi
    hi #=> NameError
    hello #=> "Hello World"
    

    编辑:请注意,这仅适用于在 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
    

    remove_method 对元数据更友好。

    【讨论】:

    • remove_method 更好,如果 hi 最初是继承或混合的。使用undef 或undef_method 将阻止调用向上传播继承/混合链。
    • 我实际上是在编辑我的答案以反映您评论 =D 时的情况
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-14
    • 2017-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多