我假設你想在Car
的其他實例方法返回之後調用Car#repair
。我看到您已經添加了其他方法也會調用repair
的要求。我在最後添加了一些關於擴展它的內容以包含內置的實例方法。
我採取的方法是利用BasicObject#method_missing:
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'...
當類Car
被解析,所有的實例方法已建成之後,可以進行以下操作我用一個例子來解釋:
instance_methods(false) # => [:repair, :drive, :checkup, :method_missing]
each_with_object({})
創建一個散列(最初爲空),由塊變量h
(稍後會詳細介紹)引用。
next if (m == :repair || m == :method_missing)
導致:repair
和:method_missing
被跳過。
當m => :drive
,以下三個語句有效地重新命名:drive
到:_drive
並添加:drive" => "_drive"
到哈希h
。
each_with_object
返回
@@ims = {:drive=>"_drive", :checkup=>"_checkup"}
現在
instance_methods(false) # => [:repair, :method_missing, :_drive, :_checkup]
因爲不再有一個方法:drive
,Car.new.drive
調用method_missing(:drive)
。後者發現@@ims
有一個密鑰:drive
,因此它使用send
來調用:_drive
,調用:repair
並返回:_drive
的返回值。如果method_missing
通過的方法不是@@ims
的密鑰,則調用super
並引發異常。
在現在刪除的編輯中,我建議要包含內置的實例方法,只需要將instance_methods(false)
更改爲instance_methods
,但會警告可能出現意外的副作用。 @Kal指出,內置的實例方法不能被刪除,所以這種方法將無法工作。這也是一樣 - 不應該以這種方式惹惱Ruby。我顯然沒有測試我的主張。恥辱!
缺乏在每種方法中調用'repair'的問題嗎? – Kal
是的。而對於像.class這樣的內置方法,它應該在那裏調用'repair'。 Car類只是我需要的一個例子。 – crownusa
爲什麼你想要這個內置的方法? – Shoe