19

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

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

4

2 回答 2

27

来自精美手册

undef_method(symbol) → self

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

所以remove_method像这样:

class CC < C
  remove_method :m
end

本质上与此相反:

class CC < C
  def m
  end
end

wheredef 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 抱怨。

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

于 2012-08-10T03:04:09.993 回答
6

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

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)

示例 2 使用remove_method

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

x 来自 A 类

于 2015-12-15T10:58:54.820 回答