From: Daniel Berger Date: 2010-01-20T01:04:22+09:00 Subject: Delayed evaluation of append_features Hi, I was just reading this bit: http://judofyr.net/posts/never-gonna-let-you-go.html And that had me wondering about my "interface" implementation. At the moment, users must declare the methods before they implement the interface. However, now I'm wondering if I could somehow delay the evaluation of append_features until *after* methods have been declared. Could continuations be used for this? Below is the code and a sample at the end. # A module for implementing Java style interfaces in Ruby. For more information # about Java interfaces, please see: # # http://java.sun.com/docs/books/tutorial/java/concepts/interface.html # module Interface # The version of the interface library. Interface::VERSION = '1.1.0a' # Raised if a class or instance does not meet the interface requirements. class MethodMissing < RuntimeError; end alias :extends :extend private def extend_object(obj) return append_features(obj) if Interface === obj append_features(class << obj; self end) included(obj) end def append_features(mod) return super if Interface === mod # Is this a sub-interface? inherited = (self.ancestors-[self]).select{ |x| Interface === x } inherited = inherited.map{ |x| x.instance_variable_get('@ids') } # Store required method ids ids = @ids + inherited.flatten @unreq ||= [] # Iterate over the methods, minus the unrequired methods, and raise # an error if the method has not been defined. (ids - @unreq).uniq.each do |id| id = id.to_s if RUBY_VERSION.to_f < 1.9 unless mod.instance_methods(true).include?(id) raise Interface::MethodMissing, id end end super mod end public # Accepts an array of method names that define the interface. When this # module is included/implemented, those method names must have already been # defined. # def required_methods(*ids) @ids = ids end alias requires required_methods # Accepts an array of method names that are removed as a requirement for # implementation. Presumably you would use this in a sub-interface where # you only wanted a partial implementation of an existing interface. # def unrequired_methods(*ids) @unreq ||= [] @unreq += ids end end class Object # The interface method creates an interface module which typically sets # a list of methods that must be defined in the including class or module. # If the methods are not defined, an Interface::MethodMissing error is raised. # # A interface can extend an existing interface as well. These are called # sub-interfaces, and they can included the rules for their parent interface # by simply extending it. # # Example: # # # Require 'alpha' and 'beta' methods # AlphaInterface = interface{ # required_methods :alpha, :beta # } # # # A sub-interface that requires 'beta' and 'gamma' only # GammaInterface = interface{ # extends AlphaInterface # required_methods :gamma # unrequired_methods :alpha # } # # # Raises an Interface::MethodMissing error because :beta is not defined. # class MyClass # def alpha # # ... # end # implements AlphaInterface # end # def interface(&block) mod = Module.new mod.extend(Interface) mod.instance_eval(&block) mod end end class Module alias :implements :include end FooInterface = interface{ requires :alpha, :beta } # How it works now class Foo def alpha;end def beta;end implements FooInterface end # How I want it to work class Foo implements FooInterface def alpha;end def beta;end end Regards, Dan