Delayed evaluation of append_features

D

Daniel Berger

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top