当写这段代码之前,我们先要分析一下如何才能去掉predefined的方法,这里有三种predefined的方法。
1 Object类本身自带的一些实例方法.
2 打开Kernel模块,或者Object类,然后动态的加入的方法。
module Kernel def name1 "bo" end end class Object def name2 "bo" end end
3 Object类include的模块里面所含有的方法:
module Name def name3 "bo" end end class Object include Name end
接下来看代码,我在里面会有注释 :
class BlankSlate class << self #首先,我们定义一个hide方法,这个方法就是隐藏掉BlankSlate类中名字为name的方法,可是instance_eval方法,或者__开头的方法,并不需要被隐藏. def hide(name) if instance_methods.include?(name.to_s) and name !~ /^(__|instance_eval)/ @hidden_methods ||= {} @hidden_methods[name.to_sym] = instance_method(name) undef_method name end end #这里提供一个可以查找一个方法是否已被隐藏的方法 def find_hidden_method(name) @hidden_methods ||= {} @hidden_methods[name] || superclass.find_hidden_method(name) end #这个是为了恢复所被隐藏的方法,首先使用上面的方法查找到方法,(这里使用了define_method,这个方法其实也就是动态的定义一个方法,name就是他的名字,详细的用法可以看我前面的文章) def reveal(name) bound_method = nil unbound_method = find_hidden_method(name) fail "Don't know how to reveal method '#{name}'" unless unbound_method define_method(name) do |*args| bound_method ||= unbound_method.bind(self) bound_method.call(*args) end end end #这里执行hide操作 instance_methods.each { |m| hide(m) } end ###################################################################### #这里解决了第二个问题,那就是当一个方法被加入的时候,能够hide这个方法(这里使用了method_added(这个方法我认为是当加入了一个方法之后,然后就会调用这个方法,name就是你所加入的方法的名字). module Kernel class << self alias_method :blank_slate_method_added, :method_added def method_added(name) result = blank_slate_method_added(name) return result if self != Kernel BlankSlate.hide(name) result end end end 这里其实我们也可以这么做: module Kernel class << self # Detect method additions to Kernel and remove them in the # BlankSlate class. def method_added(name) return super if self != Kernel BlankSlate.hide(name) super end end end ###################################################################### #这个和上面一样的。 class Object class << self alias_method :blank_slate_method_added, :method_added # Detect method additions to Object and remove them in the # BlankSlate class. def method_added(name) result = blank_slate_method_added(name) return result if self != Object BlankSlate.hide(name) result end def find_hidden_method(name) nil end end end ###################################################################### #这里是为了解决第三个问题,要注意的是append_features就是include时发生的动作,也就可以说,他其实就是include.所以这里我们必须先保存老的append_features方法,先加入mod方法,然后undef它,最后再返回其他的方法. class Module alias blankslate_original_append_features append_features def append_features(mod) result = blankslate_original_append_features(mod) return result if mod != Object instance_methods.each do |name| BlankSlate.hide(name) end result end end