实例讲解Ruby中的钩子方法及对方法调用添加钩子
钩子方法有些类似事件驱动装置,可以在特定的事件发生后执行特定的回调函数,这个回调函数就是钩子方法(更形象的描述:钩子方法可以像钩子一样,勾住一个特定的事件。),在Rails中before\after函数就是最常见的钩子方法。
Class#inherited方法也是这样一个钩子方法,当一个类被继承时,Ruby会调用该方法。默认情况下,Class#inherited什么都不做,但是通过继承,我们可以拦截该事件,对感兴趣的继承事件作出回应。
classString defself.inherited(subclass) puts“#{self}wasinheritedby#{subclass}” end end classMyString<String;end
StringwasinheritedbyMyString
通过使用钩子方法,可以让我们在Ruby的类或模块的生命周期中进行干预,可以极大的提高编程的灵活性。
对方法调用添加钩子的实例
ruby有很多有用的钩子,如included,inhered,以及method_missing。对方法调用添加钩子可以用alias环绕别名实现,但终归有些麻烦,alias_method_chain需要定义with_feature方法也较麻烦,因此实现了下列module,include后调用method_callback:before_method,:after_method即可为before_method添加after_method钩子
moduleAfterCall defself.included(base) base.extend(ClassMethods) end moduleClassMethods defafter_callwhen_call,then_call,*args_then,&block_then alias_method"old_#{when_call}",when_call define_methodwhen_calldo|*args_when,&block_when| send"old_#{when_call}",*args_when,&block_when sendthen_call,*args_then,&block_then end end end end classStudent includeAfterCall defenter_classsb puts"enterclass#{sb}" yield('before')ifblock_given? end private defafter_enter_classpop puts"afterenterclass#{pop}" yield('after')ifblock_given? end protected defthird_after puts"fromthirdenter" end after_call:after_enter_class,:third_after after_call:enter_class,:after_enter_class,"doubi",&lambda{|x|puts"fromlambda#{x}"} end Student.new.enter_class"1"do|x| puts"fromlambda#{x}" end
运行结果如下:
#enterclass1 #fromlambdabefore #afterenterclassdoubi #fromlambdaafter #fromthirdenter