ruby有很多有用的鉤子,如included,inhered,以及method_missing。對方法調用添加鉤子可以用alias環繞別名實現,但終歸有些麻煩,alias_method_chain需要定義with_feature方法也較麻煩,因此實現了下列module,include后調用method_callback :before_method,:after_method即可為before_method添加after_method鉤子,目前方法不可傳參,目前沒有解決思路
module MethodCallback
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def method_callback(before_m,after_m)
target_with = "#{before_m}_with_#{after_m}}"
target_without = "#{before_m}_without_#{after_m}"
alias_method target_without, before_m
define_method before_m do
eval(target_without)
eval(after_m.to_s)
end
alias_method target_with, before_m
end
end
end
class Student
include MethodCallback
def enter_class
puts "enter class"
end
def after_enter_class
puts "after enter class"
end
method_callback :enter_class ,:after_enter_class
end
Student.new.enter_class
今天又重新思考了下,參數問題得以解決,代碼如下
module AfterCall
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def after_call when_call,then_call,*args_then,&block_then
alias_method "old_#{when_call}",when_call
define_method when_call do |*args_when,&block_when|
send "old_#{when_call}",*args_when,&block_when
send then_call,*args_then,&block_then
end
end
end
end
class Student
include AfterCall
def enter_class sb
puts "enter class #{sb}"
yield('before') if block_given?
end
private
def after_enter_class pop
puts "after enter class #{pop}"
yield('after') if block_given?
end
protected
def third_after
puts "from third enter"
end
after_call :after_enter_class ,:third_after
after_call :enter_class ,:after_enter_class,"doubi", &lambda {|x|puts "from lambda #{x}"}
end
Student.new.enter_class "1" do |x|
puts "from lambda #{x}"
end
#運行結果如下
#enter class 1
#from lambda before
#after enter class doubi
#from lambda after
#from third enter