Hi all,

in order to clarify my understanding of the issue at hand I tried to
summarize the discussion.  Comments are welcome.

Interfaces in Ruby - the short story.

There are none.

Ok, since this was quite short, we'll try a bit harder. :-)

Interfaces in Ruby - the real story.

Technically speaking Ruby does not need interfaces since it is dynamically
typed.  Any argument list that at least satisfies the arity condition can be
handed into a method.

Since people appreciate the usage of interfaces and even more Design by
Contract (DbC) some mechanics were developed that mimic interfaces and
certain aspects of DbC.  I list them in order of increasing complexity.

(1) Document which methods a method argument must implement or its expected
type.

(2) Define a module containing the methods that all raise an exception like
this:

module FooInterface
  def bar(a,b) raise "bar(a,b) must be overridden"; end
end

class FooClass
  include FooInterface

  def bar(a,b) a+b; end
end

(3) Create a framework (like the one Paul Brannan suggested here [1]) for
defining interface methods and for checking that a particular instance
implements these methods.

(4) Try to support even more of DbC by dealing with preconditions and
postconditions like I tried in [2].

However: these things tend to get complicated and ugly, which seems to be
quite un-rubyish.  Apart from that, they never reach the robustness and
power of languages with such features built in (like Eiffel).

From the perspective of an Eiffel developer this might not be satisfactory.
But then, one should keep in mind the different focus of Ruby.  OO
capabilities are still a lot better than in Perl.

Regards

    robert


[1]
http://rm-f.net/~cout/code/ruby/treasures/RubyTreasures-0.3/lib/hacks/interf
ace.rb.html

[2] Imperfect DbC experiments:

class ConditionException < Exception; end
class PreConditionException < ConditionException; end
class PostConditionException < ConditionException; end

module Contract
  def type_check(value, type)
    raise TypeError, "#{value} is not #{type}" unless value.kind_of? type
  end

  def pre_condition_check(binding, *predicates)
    predicates.each do |p|
      raise PreConditionException, "violation of '#{p.strip}'" unless
eval(p, binding)
    end
  end

  def post_condition_check(binding, *predicates)
    predicates.each do |p|
      raise PostConditionException, "violation of '#{p.strip}'" unless
eval(p, binding)
    end
  end
end


module FooContract
  include Contract

  def bar(a,b)
    # check preconditions
    env = binding()

    type_check(a, String)
    type_check(b, Integer)

    pre_condition_check env, %{ a.length < 10 }, %{ a.length > 0 }

    # invoke method
    result = barImpl(a,b)

    # check postconditions
    env = binding()

    type_check(result, Array)
    post_condition_check env, %{ result.size == 3 }

    # finished
    return result
  end
end

class FooImpl
  include FooContract

protected
  def barImpl(a,b) [a, b, a*b]; end
end


foo = FooImpl.new

f.bar("x",3)

begin
  f.bar("x","3")
rescue Exception => e
  p e
end

begin
  f.bar("xxxxxxxxxxx",3)
rescue Exception => e
  p e
end

begin
  f.bar("",3)
rescue Exception => e
  p e
end