ruby - privados - relaciones entre clases programacion orientada a objetos
¿Cómo puede uno, sin herencia, anular un método de clase y llamar al original desde el nuevo método? (4)
Esto es un poco difícil de manejar algunas veces, pero necesita abrir la "clase propia" que es el singleton asociado a un objeto de clase específico. la sintaxis para esto es clase << self do ... end.
class Time
alias :old_strftime :strftime
def strftime
puts "got here"
old_strftime
end
end
class Time
class << self
alias :old_now :now
def now
puts "got here too"
old_now
end
end
end
t = Time.now
puts t.strftime
Encontré una fuente que Time.strftime
éxito Time.strftime
esta manera:
class Time
alias :old_strftime :strftime
def strftime
#do something
old_strftime
end
end
El problema es que strftime
es un método de instancia. Necesito anular Time.now
- un método de clase - de tal manera que cualquier persona que llama obtenga mi nuevo método, mientras que el nuevo método todavía llama al método .now
original. Miré alias_method
y no tuve éxito.
Los métodos de clase son solo métodos. Recomiendo mucho no hacerlo, pero tiene dos opciones equivalentes:
class Time
class << self
alias_method :old_time_now, :now
def now
my_now = old_time_now
# new code
my_now
end
end
end
class << Time
alias_method :old_time_now, :now
def now
my_now = old_time_now
# new code
my_now
end
end
Si necesita anularlo para fines de prueba (la razón por la que normalmente deseo anular Time.now), los marcos de burla / borrado de Ruby lo harán por usted fácilmente. Por ejemplo, con RSpec (que usa flexmock):
Time.stub!(:now).and_return(Time.mktime(1970,1,1))
Por cierto, recomiendo evitar la necesidad de eliminar Time.now dando a sus clases un reloj anulable:
class Foo
def initialize(clock=Time)
@clock = clock
end
def do_something
time = @clock.now
# ...
end
end
He estado tratando de descubrir cómo anular un método de instancia usando módulos.
module Mo
def self.included(base)
base.instance_eval do
alias :old_time_now :now
def now
my_now = old_time_now
puts ''overrided now''
# new code
my_now
end
end
end
end
Time.send(:include, Mo) unless Time.include?(Mo)
> Time.now
overrided now
=> Mon Aug 02 23:12:31 -0500 2010