>>>>> "MikkelFJ" == MikkelFJ  <mikkelj-anti-spam / post1.dknet.dk> writes:

    MikkelFJ> Are there interfaces in Ruby? If not, why not?

    MikkelFJ> However, I would like to be able to query an object
    MikkelFJ> about an interface, such that I know I can trust it to
    MikkelFJ> do the expected.

    MikkelFJ> shape_collection.each do  |obj|
    MikkelFJ>   case obj
    MikkelFJ>   when IRayIntersection
    MikkelFJ>     clip_using_interface(obj)
    MikkelFJ>   when Box
    MikkelFJ>     clip_as_rectangle(obj)
    MikkelFJ>   when Sphere
    MikkelFJ>     clip_as_circle(obj)
    MikkelFJ>   end
    MikkelFJ> end

Assuming the choice of clipping algorithm rests solely in the type of
Shape, then moving the clipping algorithm into the shape objects make
a lot of sense.  Then your code will look like ...

    shape_collection.each { |shape| shape.clip }

If a BoxWithHole can't use the standard box algorithm, it will
implement the IRayIntersection algorithm for its version of clip.  No
need to search a list of possible algorithms.  Best of all, if you add
a new algorithm there is no need to update this case statement (and
any others you might have).

On the other hand, it is possible that the choice of clipping
algorithm is dependent upon both the sender and receiver.  In other
words, clipping a box against a box is different than clipping a
circle against a box, which in turn is different from circle/circle
clipping.  This is a tougher problem.

One possibility is using a double dispatch setup like this (sorry
about the long example) ...

# START CODE ---------------------------------------------------------
module ClippingAlgorithms
  def box_circle_clip(box, circle)
    puts "Box/Circle Clipping"
  end
  def circle_circle_clip(circle1, circle2)
    puts "Circle/Circle Clipping"
  end
  def box_box_clip(box1, box2)
    puts "Box/Box Clipping"
  end
end
			    
class Circle
  include ClippingAlgorithms
  def clip(other)
    other.circle_clip(self)
  end
  def circle_clip(circle)
    circle_circle_clip(self, circle)
  end
  def box_clip(box)
    box_circle_clip(box, self)
  end
end

class Box
  include ClippingAlgorithms
  def clip(other)
     other.box_clip(self)
  end
  def circle_clip(circle)
    box_circle_clip(self, circle)
  end
  def box_clip(box)
    box_box_clip(self, box)
  end
end

b = Box.new
c = Circle.new

b.clip(b)  #=> Box/Box Clipping
c.clip(c)  #=> Circle/Circle Clipping
b.clip(c)  #=> Box/Circle Clipping
c.clip(b)  #=> Box/Circle Clipping
# END CODE -----------------------------------------------------------

The downside is that adding new shapes causes an explosion of new
combinations.  Sometimes this can be mitigated through judicious use
of inheritance.

If you don't need the complexity, obviously the first solution is much
better.

-- 
-- Jim Weirich     jweirich / one.net    http://w3.one.net/~jweirich
---------------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct, 
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)