On Wed, 19 Nov 2003 08:08:25 +0900, Sean O'Dell wrote:
> This was my thinking as well. I don't like the idea of strong
> typing at all in Ruby, but I do very much like the idea of being
> able to simply ask (or assert that) object.is_a?(:id) and get an
> answer that basically says "this object has :id somewhere in its
> hierarchy, either because its class is a superclass of :id or :id
> is a module that was mixed-in at some point."

That can be useful, but it tells you less than you think. As Jim
Weirich pointed out, it introduces fragility.

> All I ever really care about is knowing whether or not an object
> implements a certain interface, and that interface can either be
> described as a mix-in module or an ancestor class. It doesn't
> really matter to me where that interface was defined, any class or
> module will do; the object could also be much more evolved than I
> expect it to be, and could even have lots of methods overridden. I
> don't really care. All I care about is if it is *at least*
> implementing a certain basic interface.

Ancestry/name checking doesn't tell you that a method implements a
certain interface. It says that it inherits from a class or includes
a module. You can assume that a name indicates an interface, but
that's a bad assumption:

  class File
    class << self
      undef :read
    end
  end

Oops! Now you've got something that's a File, but doesn't correspond
to the required interface. Granted, this is a pathological case, but
I could see this sort of thing being done in a sandbox situation.

> It would also be nice if I could specify that certain method
> parameters can only be objects containing a certain interface. For
> example:

>   def mymethod(:SomeModule a)
>   end

> ...where Ruby automatically asserts for me that a has :SomeModule
> somewhere in its hierarchy, and throws an appropriate exception if
> it does not.

Blech. I don't want Java. You're talking exactly what Ryan's
StrongTyping module does, and assuming that a name accurately
represents an interface.

> In fact, it would be also great if, instead of having to derive
> from or mix-in an interface, I could just say:

> class MyClass
>   interface :SomeModule
> end

This is easy enough to implement, since interface would simply be a
private class or module method.

Ultimately, I don't see a real value add with any of these
proposals. (Either the empty "interface" modules or the above. The
empty "interface" modules wouldn't work for IO in any case, since IO
is a class as well.)

If you want to ensure something conforms to an expected interface,
test that interface. For example, adapted from Text::Format:

  def hyphenator=(x)
    raise unless x.respond_to?(:hyphenate_to)
    raise unless [2, 3].include?(x.method(:hyphenate_to).arity)
    @hyphenator = x
  end

This would be simplified by my proposed change to #respond_to?
(although it wouldn't *really* help in this case; I'd need to have
an Array version).

-austin
--
austin ziegler    * austin / halostatue.ca * Toronto, ON, Canada
software designer * pragmatic programmer * 2003.11.19
                                         * 01.12.05