2012-08-10 14 views
14

Ich möchte eine Methode neu definieren, aber vermeiden Sie die damit verbundene Warnung. Sollte ich undef_method oder remove_method dazu verwenden?Wann undef_method und wann remove_method?

(Ja, Hacky ist ein wenig Methoden neu zu definieren. Ich das tue, weil ich einige memoization, dass ich, wenn Unit-Tests verwenden mag laufen werden, aber nicht, wenn das Programm selbst ausgeführt wird.)

Antwort

20

von den fine manual:

undef_method (Symbol) → Selbst

Verhindert, dass die aktuelle Klasse von Anrufen auf das genannte Verfahren reagiert. Vergleichen Sie dies mit remove_method, die die Methode aus der bestimmten Klasse löscht; Ruby sucht immer noch Superklassen und gemischte Module für einen möglichen Empfänger.

So ein remove_method wie folgt aus:

class CC < C 
    remove_method :m 
end 

ist im Wesentlichen das Gegenteil davon:

class CC < C 
    def m 
    end 
end 

Wo def m die Methode m der Klasse fügt hinzu: remove_method :m entfernt m. Aber wenn die Superklasse eine m Methode hat, wird diese immer noch verwendet.

undef_method, OTOH, ist wie folgt:

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

So undef_method die Methode tatsächlich nicht entfernen, das Verfahren mit einer speziellen internen Flagge ersetzt, die Ruby führt zu beschweren, wenn Sie anrufen versuchen, dass Methode.

Klingt wie Sie versuchen, eine vorhandene Methode zu ersetzen und ersetzen ist semantisch das gleiche wie einentfernen, gefolgt von einem hinzufügen so remove_method wahrscheinlich besser geeignet. Wenn Sie jedoch paranoid sein und sicherstellen möchten, dass die Ersatzmethode vorhanden ist, dann wäre undef_method nützlich; oder, wenn Sie aus irgendeinem Grund die Methode an einem Ort entfernen und in einem anderen hinzufügen müssen, würde undef_method Ihnen zumindest sagen, dass Sie nur die Hälfte der Arbeit getan haben, während remove_method Sie entweder mit der Implementierung der Superklasse verlassen würde (und möglicherweise seltsamen Bugs) oder eher verwirrend NoMethodError.

+0

Ehrfürchtig Erklärungen. –

4

Sie können eine Methode auf zwei einfache Arten entfernen. Die drastische

Module#undef_method() 

entfernt alle Methoden, einschließlich der vererbten Methoden. Die kinder

Module#remove_method() 

entfernt das Verfahren von dem Empfänger, aber es Blätter Methoden allein geerbt.

unter 2 einfaches Beispiel Siehe -

Beispiel 1 unter Verwendung 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 

Ergebnis - main.rb: 15: in ': undefined method x‘für # (NoMethodError)

Beispiel 2 unter Verwendung von 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 

Ergebnis - $ Rubin main.rb

x von A-Klasse

Verwandte Themen