2012-08-10 36 views
14

Chcę przedefiniować metodę, ale unikaj ostrzeżenia z nią związanego. Czy należy użyć metody undef_method lub remove_method, aby to zrobić?Kiedy używać undef_method i kiedy używać metody remove_method?

(Tak, przedefiniowanie metod jest trochę hacky. Robię to, bo mam trochę memoization że chcę użyć gdy testy jednostkowe są uruchamiane, ale nie wtedy, gdy sam program jest uruchamiany.)

Odpowiedz

20

od fine manual:

undef_method (symbol) → siebie

Zapobiega aktualną klasę z reaguje na wezwania do nazwanego metody. Porównaj to z remove_method, który usuwa metodę z konkretnej klasy; Ruby będzie nadal wyszukiwać superklasy i mieszane moduły dla możliwego odbiorcy.

Więc remove_method tak:

class CC < C 
    remove_method :m 
end 

jest w zasadzie przeciwieństwem tego:

class CC < C 
    def m 
    end 
end 

Gdzie def m dodaje metodę m do klasy, remove_method :m usuwa m. Ale jeśli super klasa ma metodę m, to nadal będzie używana.

undef_method, OTOH, jest bardziej jak to:

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

Więc undef_method faktycznie nie usunąć metodę, zastępuje metodę specjalną flagą wewnętrznego, które powoduje Ruby narzekać, jeśli starają się nazwać metoda.

Brzmi jak próbujesz zastąpić istniejące metody i zastąpić jest semantycznie taka sama jak usunięcia następnie przez dodać tak remove_method jest chyba bardziej odpowiednie. Jednakże, jeśli chcesz być paranoikiem i upewnić się, że metoda wymiany jest na miejscu, to przydałby się undef_method; lub, jeśli z jakiegoś powodu musisz usunąć metodę w jednym miejscu i dodać ją w innym, undef_method powie Ci przynajmniej, że wykonałeś tylko połowę pracy, podczas gdy remove_method albo zostawiłoby ci implementację superklasy (i możliwe dziwne błędy) lub raczej mylące NoMethodError.

+0

Wypasione wyjaśnień. –

4

Możesz usunąć metodę na dwa proste sposoby. Drastyczne usunięcie wszystkich metod, włącznie z odziedziczonymi, jest drastyczne. Kinder

Module#remove_method() 

usuwa metodę z odbiornikiem, ale pozostawia dziedziczone metody sam.

Poniżej 2 prosty przykład -

Przykładzie 1 stosując 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 

rezultacie - main.rb: 15: w ': undefined method x”o # (NoMethodError)

Przykład 2 przy użyciu 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 

Wynik - $ ruby ​​main.rb

X z klasy

Powiązane problemy