From: Sean O'Dell Date: 2003-11-19T08:08:25+09:00 Subject: Re: "stereotyping" (was: Re: Strong Typing (Re: Managing metadata about attribute types) ) On Tuesday 18 November 2003 02:06 pm, Simon Kitching wrote: > > There can be an interface defining what it means to "be an IO". Any > object which does in fact behave exactly in accordance with this > contract should mark itself as being an implementation of that > interface. > > I suggest this approach: > > # an IO object fulfils the following contract: > # ... details here ... > module IO; end # note: no implementation!!! > > class StringIO > # declare that this class fulfils the IO contract > include IO > ... > end > > class File > # declare that this class fulfils the IO contract > include IO > ... > end > > Now someobj.is_a?(IO) will return true for all those objects which > fulfil the IO contract. Note that the IO module does *not* have any > implementation; it is purely an abstract concept and therefore can be > mixed in to any existing class. When mixed in, it functions as a promise > of behaviour which can be checked for at runtime. > > > I expect that some people will put forward the idea that some class > might be invented that happens to also fulfil the IO contract without > being explicitly marked so, and that checking for the "IO" marker would > disallow passing this class. Well I think the chances of a class > happening to exactly fulfil a contract without that contract ever have > being taken into consideration is smaller than the chance of us all > being wiped out by an asteroid. > > Note that checking for *concrete* classes using is_a is a totally > different issue. That does present problems regarding the inheritance > tree, because you can't just mix in such a type to any other type. I > think the arguments against this pattern are on much stronger ground. 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." 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. 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. 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 ...which would act as though :SomeModule were mixed-in, except it's basically lying. If the author of MyClass didn't really implement the interface described my :SomeModule, KA-BOOM. But oh well, such is life. I like the combination of "can do" with "can do it wrong." It's freedom. In this way, some modules can be purely for interface describing. You could make phony modules whose only purpose is to describe the interface, then write classes that implement the interface and declare themselves as such. This would be very, very nice to have. Sean O'Dell