=begin = preserved.rb == SYNOPSIS require "preserved" class XXX def foo # ... should not be redefined ... end preserved :foo end class YYY < XXX def foo #########!! NameError raised here == CLASS Module === METHODS : preserved(name...) Prohibits redefining the methods specified by name. We call these methods "preserved methods". : preserved_methods Returns an array which consists of preserved methods. =end class Module PRESERVED_VERSION = "2001-07-20" def preserved(*meth) instance_eval %q{ Preserved_methods = [] unless defined?(Preserved_methods) meth.each do |m| m = m.id2name if m.is_a? Symbol if ! m.is_a? String raise ArgumentError, "#{m} is not a symbol" elsif ! instance_methods.include? m raise NameError, "undefined method `#{m}' for class #{self}" end Preserved_methods.replace(Preserved_methods | [m]) end } end def preserved_methods instance_eval %q{ Preserved_methods = [] unless defined?(Preserved_methods) Preserved_methods.dup } end private def method_added(id) catch(:preserved!) do instance_eval %q{ return if id == :method_added Preserved_methods = [] unless defined?(Preserved_methods) if Preserved_methods.include? id.id2name throw :preserved! end } return end raise NameError, "preserved method `#{id}' redefined for class #{self}" end end if __FILE__ == $0 _,demo,_=<<'=== EXAMPLE',<<"== AUTHORS",<<"=end";eval demo # Forget this ;-) =begin === EXAMPLE class C def a; end p [1, C, preserved_methods] #=> [1, C, []] preserved :a p [2, C, preserved_methods] #=> [2, C, ["a"]] end class S < C p [3, S, preserved_methods] #=> [3, S, ["a"]] def a0; end preserved :a0 p [4, S, preserved_methods] #=> [4, S, ["a", "a0"]] end class C p [5, C, preserved_methods] #=> [5, C, ["a"]] end class S def a; end #!! preserved method `a' redefinded for class S end == AUTHORS Gotoken == HISTORY 2001-07-20: Preserved_method would be modified by replace (kg) 2000-10-17: First release (gotoken@notwork.org) =end end