# Delayed evaluation of append\_features

**URL:** <https://www.ruby-forum.com/t/delayed-evaluation-of-append-features/181880>\
**Category:** Ruby\
**Created:** [January 19, 2010, 5:04pm UTC](https://www.ruby-forum.com/t/delayed-evaluation-of-append-features/181880 "2010-01-19T17:04:59Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![danielb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/c57346/32.png) [@danielb](https://www.ruby-forum.com/u/danielb)\
**Post date:** [January 19, 2010, 5:04pm UTC](https://www.ruby-forum.com/t/delayed-evaluation-of-append-features/181880/1 "2010-01-19T17:04:59Z")

</div>

Hi,

I was just reading this bit:

[http://judofyr.net/posts/never-gonna-let-you-go.html](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)](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
