2012-08-10 28 views
14

Quiero redefinir un método, pero evito la advertencia asociada. ¿Debo usar undef_method o remove_method para hacerlo?Cuándo usar undef_method, y cuándo usar remove_method?

(Sí, la redefinición de los métodos es un poco hacky. Estoy haciendo esto porque tengo algunos memoization que yo quiero usar pruebas unitarias cuando están en ejecución, pero no cuando el propio programa se ejecuta.)

Respuesta

20

desde el fine manual:

undef_method (símbolo) → auto

Previene la clase actual de responder a las llamadas al método llamado. Contraste esto con remove_method, que elimina el método de la clase particular; Ruby seguirá buscando superclases y módulos mixtos para un posible receptor.

Así que un remove_method así:

class CC < C 
    remove_method :m 
end 

es esencialmente lo contrario de esto:

class CC < C 
    def m 
    end 
end 

Dónde def m agrega el método m a la clase, remove_method :m elimina m. Pero, si la superclase tiene un método m, se seguirá utilizando.

undef_method, otoh, es de la misma familia:

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

Así undef_method en realidad no quitar el método, se sustituye el método con un indicador interno especial que hace que Ruby a quejarse si se intenta llamar a ese método.

Parece que usted está tratando de reemplazar un método existente y reemplazar es semánticamente lo mismo que un eliminar seguido de un añadir por lo remove_method es probablemente más apropiado. Sin embargo, si desea ser paranoico y asegurarse de que el método de reemplazo esté en su lugar, entonces undef_method sería útil; o, si por alguna razón necesita eliminar el método en un lugar y agregarlo en otro, undef_method al menos le diría que solo hizo la mitad del trabajo, mientras que remove_method lo dejaría con la implementación de la superclase (y posibles errores extraños).) o un confuso NoMethodError.

+0

explicaciones impresionantes. –

4

Puede eliminar un método de dos maneras sencillas. El drástico

Module#undef_method() 

elimina todos los métodos, incluidos los heredados. El Kinder

Module#remove_method() 

quita el método del receptor, pero hojas métodos heredados solo.

Ver por debajo de 2 ejemplo sencillo -

Ejemplo 1 usando 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 

resultado - main.rb: 15: en ': undefined method x' para # (NoMethodError)

Ejemplo 2 usando 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 

Resultado - $ rubí main.rb

x de una clase

Cuestiones relacionadas