ruby学习笔记之include/prepend


ruby 寻找方法时 先右后上。先找类,再找父类...

如果使用include/prepend 则变成

测试用例

class Super_class
	def func
		puts "func from SuperClass"
	end
end
module Module_prepend
	def func
		puts "func from Module_prepend"
		super
	end
end
module Module_include
	def func
		puts "func from Module_include"
		super
	end
end
class Kclass < Super_class
	include Module_include
	prepend Module_prepend
	def func
		puts "func from Class"
		super 
	end
end


Kclass.new.func 
=begin
将会输出 	
func from Module_prepend
func from Class
func from Module_include
func from SuperClass
=end




#如果有个Work#do 需要我们监视它的耗时情况,原始的工作情况如下
class VirtaualWork
	def do(&block)
		puts "VirtaualWork#do"
		block.call block if block_given?
	end
end
class Work < VirtaualWork
	def do
		puts "Work#do"
		sleep(rand(3))
		super
	end
end
Work.new.do { puts "work end at #{Time.now}" }
#Work#do
#VirtaualWork#do
#work end at 2016-08-02 18:23:54 +0800



当然我们需要的不是修改原始的do方法,而是扩展Work类,使它具有新的能力。现在重新打开Work

class Work 
include Watch_filter
watch_method :do
end


等等 Watch_filter 是什么鬼,watch_method又是什么东东,其实我们要稍后才会实现它。从字面上理解我们只是说我们希望Work能有一个新的能力,能监视do方法,简单的在方法被调用之前记下时间,在方法被调用之后能查出耗时并输出。这个扩展的能力将由Watch_filter module提供,下面我们来看看这个模块的实现

module Watch_filter
	def self.included(kclass)
		#Module.included是一个回调方法,当其它的类或模块include了此模块时,将会回调此方法
		kclass.extend(Ext_methods)
	end
	
	module Ext_methods
		#mixin Watch_filter模块的类都将会有新的Klass.watch_method方法的能力
		def watch_method(method_name)
			#prepend一个匿名模块。重新定义method_name方法
 			prepend_mod=Module.new do 
				define_method(method_name) do |*args,&block|
					puts "prepend module##{method_name}"
					instance_variable_set(:@start_method_time,Time.now)
					super(*args,&block)
				end
			end
			prepend prepend_mod
			#include 一个匿名模块,重新定义method_name方法
			include_mod= Module.new do 
				define_method(method_name) do |*args,&block|
					puts "include module##{method_name}"
					super(*args,&block)
					puts "work#do spend time #{Time.now - @start_method_time}"
				end
			end
			include include_mod
		end
	end
end


class Work 
	include Watch_filter
	watch_method :do
end


work=Work.new.do { puts "work end at #{Time.now}" }
#prepend module#do
#Work#do
#include module#do
#VirtaualWork#do
#work end at 2016-08-02 18:23:55 +0800
#work#do spend time 1.00316


魔法在这里
puts Work.ancestors.to_s
[#<Module:0x007fdf8b9362b0>, Work, #<Module:0x007fdf8b9360f8>, Watch_filter, VirtaualWork, Object, Kernel, BasicObject]

work#do会先找到prepend module的do方法,然后由super一直上溯到VirtaualWork

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值