Ich habe angenommen, dass Sie Car#repair
aufgerufen werden sollen, nachdem jede andere Car
andere Instanz Methoden zurückgegeben haben. Ich sehe, dass Sie eine Anforderung hinzugefügt haben, die andere Methoden auch aufrufen repair
. Ich habe am Ende einige Anmerkungen hinzugefügt, um dies auf integrierte Instanzmethoden auszudehnen.
Der Ansatz, den ich gemacht habe, ist die Verwendung von BasicObject#method_missing zu machen:
class Car
def repair
puts "Repaired!"
end
def drive
puts "Drive!"
end
def checkup
puts "Checkup!"
end
def method_missing(m, *args)
if @@ims.key?(m)
ret = send(@@ims[m], *args)
repair
ret
else
super
end
end
@@ims = instance_methods(false).each_with_object({}) do |m,h|
next if (m == :repair || m == :method_missing)
saved_name = "_#{m}"
alias_method saved_name, m
h[m] = saved_name
remove_method(m)
end
end
car = Car.new
car.repair
Repaired!
car.drive
Drive!
Repaired!
car.checkup #
Checkup!
Repaired!
car.wash # => in `method_missing': undefined method `wash'...
Wenn Klasse Car
analysiert wird, nachdem alle Instanzmethoden konstruiert worden sind, werden die folgenden Operationen sind durchgeführt, was ich anhand eines Beispiels erkläre:
instance_methods(false) # => [:repair, :drive, :checkup, :method_missing]
each_with_object({})
erzeugt einen Hash (zunächst leer), auf den sich die Blockvariable h
bezieht (mehr dazu später).
next if (m == :repair || m == :method_missing)
:repair
und :method_missing
verursacht werden übersprungen.
Wenn m => :drive
die folgenden drei Aussagen effektiv :drive
-:_drive
umbenennen und fügen :drive" => "_drive"
zu dem Hash-h
.
each_with_object
kehrt
@@ims = {:drive=>"_drive", :checkup=>"_checkup"}
und jetzt
instance_methods(false) # => [:repair, :method_missing, :_drive, :_checkup]
Da es nicht mehr ist eine Methode :drive
, Car.new.drive
ruft method_missing(:drive)
. Letzteres findet, dass @@ims
einen Schlüssel :drive
hat, so verwendet es send
, um :_drive
aufzurufen, ruft :repair
auf und gibt den Rückgabewert :_drive
zurück. Wenn method_missing
übergeben wird, wird eine Methode aufgerufen, die kein Schlüssel von @@ims
ist, super
wird aufgerufen, und eine Ausnahme wird ausgelöst.
In einer jetzt entfernten Bearbeitung schlug ich vor, integrierte Instanzmethoden einzubeziehen, man muss nur instance_methods(false)
in instance_methods
ändern, aber vor möglichen unbeabsichtigten Nebenwirkungen gewarnt werden. @Kal wies darauf hin, dass integrierte Instanzmethoden nicht entfernt werden können, so dass der Ansatz nicht funktioniert.Das ist auch gut - man sollte sich auf diese Weise nicht mit Ruby anlegen. Ich habe meine Behauptung offensichtlich nicht geprüft. Schande!
Kurz vor dem Aufruf von 'repair' in jeder Methode? – Kal
ja. Und für eingebaute Methoden wie ".class" sollte es 'repair' dort nennen, to. Die Klasse "Car" ist nur ein Beispiel für das, was ich brauche. – crownusa
Warum willst du das für eingebaute Methoden? – Shoe