2011-05-06 13 views
8

En Ruby, cuando se alias un método, el alias apunta al cuerpo del método original. Entonces, incluso si redefine el método original, el alias continuará usando la definición original.¿Puedes anular un método de alias en Ruby?

class Foo 
    def bar 
    "bar" 
    end 
    alias :saloon :bar 
end 

class Foo 
    def bar 
    "BAR" 
    end 
end 

puts Foo.new.saloon 

devolverá 'bar' y no 'BAR'. ¿Hay alguna manera de hacer que el salón use la nueva definición de barra?

EDITAR: Debería haber sido más claro. El ejemplo fue solo una ilustración del problema: no es el problema real que necesito resolver. El problema es más complejo cuando tienes alias encadenados, por ejemplo, en el núcleo de Rails. P.ej. perform_action es un alias del módulo de evaluación comparativa, y luego también del módulo flash. Así que ahora una llamada a perform_action en realidad está llamando a perform_action_with_flash, lo que hace es una cosa, entonces efectivamente llama a perform_action_with_benchmarking, que luego llama al perform_action original. Si quiero anular perform_action_with_benchmarking (aunque estoy de acuerdo en que es una mala idea, por favor no nos metamos en una discusión de eso, ya que está más allá del punto), no puedo porque ha sido un alias, y por lo que puedo decir, alias apunta a lo que es esencialmente una copia del original perform_action_with_benchmarking, por lo que incluso si lo redefino, no hay ningún efecto.

+1

+1 Gracioso (e interesante). –

Respuesta

2

Aquí hay otra respuesta, pero usted tiene que realizar algunos pasos adicionales: recoger los alias antes de primer orden, y realias después:

class Class 
    def get_aliases method_name 
    original_proc = instance_method method_name 
    aliases = [] 
    instance_methods.each do |meth| 
     # if the methods have different names but they're the same, they're aliased 
     if meth != method_name.to_s && original_proc == instance_method(meth) 
     aliases << meth 
     end 
    end 
    aliases 
    end 
end 

class Foo 
    def bar 
    "bar" 
    end 
    alias :saloon :bar 
end 

class Foo 
    aliases = get_aliases :bar 
    def bar 
    "BAR" 
    end 
    aliases.each { |a| alias_method a, :bar } 
end 

puts Foo.new.saloon #=> BAR 

Por cierto, si alguien puede quitarse uno de que los pasos, se puede saber ¡eso! :)

+0

Esa es una manera inteligente de determinar qué métodos tienen un alias. Creo que haría el truco ... – farhadf

+0

Espero que sí. ¡Gracias! :) –

4

Sólo volver a establecer el alias:

class Foo 
    def bar 
    "bar" 
    end 
    alias :saloon :bar 
end 

class Foo 
    def bar 
    "BAR" 
    end 
    alias :saloon :bar 
end 

puts Foo.new.saloon # => "BAR" 
3
class Foo 
    def bar 
    "bar" 
    end 
    def saloon 
    bar 
    end 
end 

Esto no es un alias en absoluto, pero funciona como desee.

0

Sí y no. O las soluciones de Coreyward o Sony Santos funcionan bien. Lo que necesita saber es por qué su código no funcionó de la manera que usted pensó.

alias crea un nuevo nombre para la función tal como aparece cuando se invoca el método. Esto es no un puntero, sino una nueva forma de referirse a algo. Nos permite hacer algo como esto:

class Foo 
    def bar 
    "bar" 
    end 
    alias :speakeasy :bar 
end 

class Foo 
    def bar(secret_code = false) 
    return speakeasy if secret_code == "A friend of Al" 
    "Closed because of prohibition!" 
    end 
end 

puts Foo.new.bar #=> "Closed because of prohibition!" 
puts Foo.new.bar "A friend of Al" #=> "bar" 

El antiguo bar todavía existe, es sólo un poco más difícil para acceder ahora.

Cuestiones relacionadas