19

メソッドを再定義したいのですが、それに関連する警告は避けてください。そのために undef_method または remove_method を使用する必要がありますか?

(はい、メソッドの再定義は少しハックです。これを行っているのは、プログラム自体の実行時ではなく、単体テストの実行時に使用したいメモ化があるためです。)

4

2 に答える 2

27

細かいマニュアルから:

undef_method(シンボル) → 自己

現在のクラスが名前付きメソッドの呼び出しに応答しないようにします。remove_methodこれを、特定のクラスからメソッドを削除すると対比してください。Ruby は引き続きスーパークラスと混合モジュールを検索して、可能な受信者を探します。

したがって、次のremove_methodようになります。

class CC < C
  remove_method :m
end

は本質的にこれの反対です:

class CC < C
  def m
  end
end

メソッドをクラスにdef m追加し、 を削除します。ただし、スーパークラスにメソッドがある場合は、それが引き続き使用されます。mremove_method :mmm

undef_method、OTOHは、次のようになります。

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

そのundef_methodため、実際にメソッドを削除するのではなく、そのメソッドを呼び出そうとすると Ruby にエラーを発生させる特別な内部フラグでメソッドを置き換えます。

既存のメソッドを置き換えようとしているように聞こえますが、replaceは意味的にremoveの後にadd を行うのと同じであるためremove_method、おそらくより適切です。ただし、妄想的になりたい場合や、置換方法が整っていることを確認したい場合は、undef_method便利です。または、何らかの理由である場所でメソッドを削除して別の場所に追加する必要がある場合undef_method、少なくとも半分の仕事しかできなかったことがremove_methodわかりますが、スーパークラスの実装(および奇妙なバグの可能性)が残るか、かなり紛らわしいNoMethodError

于 2012-08-10T03:04:09.993 に答える
6

メソッドは 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)

例 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

×Aクラスから

于 2015-12-15T10:58:54.820 に答える