2012-08-10 24 views
14

メソッドを再定義したいが、それに関連する警告は避けたい。 undef_methodまたはremove_methodを使用してこれを行う必要がありますか? undef_methodを使用するタイミングとremove_methodを使用するタイミングは?

(はい、メソッドを再定義すると、私はユニットテストが実行されているときに使用するいくつかのメモ化を持っているので、私はこれをやっている。少しハックですが、プログラム自体が実行されていないとき。)

答えて

20

fine manualから:

undef_method(シンボル)→自己

は、名前のメソッドの呼び出しに応答してから現在のクラスのを防ぎます。特定のクラスからメソッドを削除するremove_methodと対比してください。 Rubyは可能な受信機のためにスーパークラスと混在モジュールを検索します。

ので、このようなremove_method

class CC < C 
    remove_method :m 
end 

は、本質的にこれの逆である:

def mがクラスにメソッドを追加します m
class CC < C 
    def m 
    end 
end 

remove_method :mmを削除します。しかし、もしスーパークラスがmメソッドを持っていれば、それはまだ使用されます。

undef_method、OTOH、より多くのこのようなものです:だからundef_methodが実際にメソッドを削除しません。あなたはそれを呼び出そうと

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

、それはRubyが文句を起こす特殊な内部フラグを持つメソッドを置き換えます方法。

では、既存のメソッドを置き換えるためにしようとしているような音やを交換remove_methodは、おそらくより適切であるので、を追加し、意味的にを削除続いと同じです。しかし、あなたが妄想的になり、置換方法が適切であることを確認したい場合は、undef_methodが便利です。または何らかの理由で1つの場所でメソッドを削除して別の場所に追加する必要がある場合は、undef_methodは少なくとも、ジョブの半分しか実行しなかったと言いますが、remove_methodはスーパークラスの実装を残します)またはかなり混乱しているNoMethodError

+0

恐ろしい説明。 –

4

メソッドを削除するには、2つの方法があります。抜本的な

Module#undef_method() 

は、継承されたものを含むすべてのメソッドを削除します。

Module#remove_method() 

親切が受信機からメソッドを削除しますが、それ 葉が一人でメソッドを継承しています。

2簡単な例を下に見る - main.rb - を用い

例1

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 

結果undef_method:15: ': undefined method X」位(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 

結果 - クラスから $ルビーmain.rb

X