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:
What Is an Interface? (The Java™ Tutorials > Learning the Java Language > Object-Oriented Programming Concepts)
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