【问题标题】:When to use undef_method, and when to use remove_method?什么时候用undef_method,什么时候用remove_method?
【发布时间】:2012-08-07 07:42:59
【问题描述】:

我想重新定义一个方法,但要避免与之相关的警告。我应该使用 undef_method 还是 remove_method 这样做?

(是的,重新定义方法有点麻烦。我这样做是因为我有一些我想在运行单元测试时使用的记忆,而不是在运行程序本身时使用。)

【问题讨论】:

    标签: ruby reflection methods metaprogramming


    【解决方案1】:

    来自fine manual

    undef_method(symbol) → self

    防止当前类响应对命名方法的调用。将此与remove_method 进行对比,后者从特定类中删除方法; Ruby 仍会在超类和混合模块中搜索可能的接收器。

    所以remove_method 是这样的:

    class CC < C
      remove_method :m
    end
    

    本质上与此相反:

    class CC < C
      def m
      end
    end
    

    def m 将方法 m 添加到类中,remove_method :m 删除 m。但是,如果超类有一个m 方法,那么它仍然会被使用。

    undef_method,OTOH,更像是这样的:

    class CC < C
      def m
        raise 'No, you cannot do that.'
      end
    end
    

    所以undef_method 实际上并没有删除该方法,它用一个特殊的内部标志替换该方法,如果您尝试调用该方法,Ruby 会报错。

    听起来您正在尝试替换现有方法,而 replace 在语义上与 remove 后跟 add 相同,所以 @ 987654334@ 可能更合适。但是,如果您想偏执并确保替换方法到位,那么undef_method 会很有用;或者,如果由于某种原因您需要在一个地方删除该方法并将其添加到另一个地方,undef_method 至少会告诉您您只完成了一半的工作,而remove_method 会留下超类的实现(和可能的奇怪错误)或相当混乱的NoMethodError

    【讨论】:

    • 很棒的解释。
    【解决方案2】:

    您可以通过两种简单的方式删除方法。剧烈的

    Module#undef_method( ) 
    

    删除所有方法,包括继承的方法。善良的人

    Module#remove_method( ) 
    

    从接收器中删除方法,但它 保留继承的方法。

    见下面2个简单的例子-

    示例 1 使用 undef_method

    class A 
        def x
            puts "x from A class"
        end
    end
    
    class B < A
        def x
            puts "x from B Class"
        end
        undef_method :x
    end
    
    obj = B.new
    obj.x
    

    结果 - main.rb:15:in ': undefined methodx' for # (NoMethodError)

    使用 remove_method

    的示例 2
    class A 
        def x
            puts "x from A class"
        end
    end
    
    class B < A
        def x
            puts "x from B Class"
        end
        remove_method :x
    end
    
    obj = B.new
    obj.x
    

    结果 - $ruby main.rb

    来自A类的x

    【讨论】:

      猜你喜欢
      • 2011-09-28
      • 2012-04-05
      • 1970-01-01
      • 2020-01-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多