On Wednesday, October 16, 2002, at 02:34 PM, Paul Brannan wrote:

> On Thu, Oct 17, 2002 at 12:45:41AM +0900, Chris Gehlker wrote:
>>> This doesn't make sense to me.  I see interfaces and mixins as
>>> orthogonal concepts; interfaces are used to specify a contract, while
>>> mixins are used to provide additional methods to a class.
>>
>> It's just that the contract is used as a weak form of multiple
>> inheritance. At least I've never seen it used any other way.
>
> I think that MI can be used to implmement the contract, but that does
> not mean that the contract is a form of MI.
>

I was just  expressing the conventional wisdom. See for example, Sun's 
Java tutorial or here;
http://research.sun.com/techrep/1993/abstract-21.html

>> And it is called "Interface Inheritance" because it allows the
>> programmer to add functionality to a class that is orthogonal to the
>> functionality of the main inheritance path. For example if bird
>> inherits from animal and implements flight then a bird 'is a' animal
>> but a bird also 'is a' flier. In Ruby I'd just make flight a mixin.
>
> Interface inheritance does not add any functionality to a class.
>
Agreed.

> The goals behind an interface or abstract class are:
>   1) Be able to write a function that can take as a parameter any 
> object
>      that inherits from the abstract class (generic programming).

I don't agree that an interface, in the Java sense, and an abstract 
class, in the Java/C++ sense are synonymous or that an interface has 
necessary relationship to generic programming. Generic programming came 
out of C++, which has no notion of interface.

>   2) Be able to easily determine whether a given concrete class has a
>      particular set of features
>


> In Ruby:
>   - #1 is unnecessary in Ruby, because any method can accept any object
>     as a parameter.
>   - #2 is the source of an ongoing debate on ruby-talk.
>
> If there are other uses for interface inheritance (besides derivatives
> of the above), then I am yet to see them in use.

I believe the most common uses of the abstract class are:

1) To provide code clarity and to avoid code duplication
2) To provide a way of referencing an object who's type is not 
determined until run time, for example, the elements of a display list 
in a drawing program.

There are also:
3) Idiosyncratic but very clever uses as, for example, in the STL, 
where it is somewhat obscured by all the template stuff, and in GNUStep 
where it isn't.

Motivation 2 disappears in dynamic langaguages. 1 and 3 remain.

>
>>> What is a "class cluster"?  Can you provide an example?
>>
>> Lets start with the hoary example from C++ of the abstract class shape
>> whose only non-virtual methods are move and resize where resize
>> operates on a circumscribed rectangle and whose only attributes are 
>> the
>> coordinates of the bounding rectangle. To do something similar in
>> dynamic languages, you define a class shape with move and resize
>> methods but you make shape's new method private. Then you define
>> concrete constructors such as create_circle_with_radius(r) and
>> create_rectangle_with_sides(length, width) etc. Of course you derive
>> circle, rectangle,  pentagon and friends from shape. You can call
>> draw(boundingBox) in shapes move and resize methods so long as every
>> child of shape defines a draw method.
>>
>> Shape is called a class cluster because the private constructor
>> guarantees that any variable referencing a shape is actually
>> referencing a member of a concrete subclass. Use it as you would an
>> abstract class.
>>
>> I hope that helps. It was pretty condensed so ask again if it's
>> confusing. I'll try to provide a better example.
>
> Yes, it's confusing.  I tried implementing your example in Ruby, but I
> ran into the following problems:
>   1) If resize is a method of Shape, then what parameters does it take?
>      For a Circle, I would expect it to take a radius, but for a
>      Rectangle, I would expect it to take a length and a width.

All shapes are resized by dragging a handle on their bounding box. This 
is the way real drawing programs work. One would not expect the user to 
learn a different resizing method for each type of shape. The bounding 
box method is generic. That's why it belongs in the virtual/cluster 
base class.

>   2) I could not figure out how to define a concrete constructor for
>      Rectangle while still making it impossible to accidentally
>      instantiate a Rectangle without going through the factory method
>      (if I can't call Rectangle.new, then neither can the factory
>      method).

There is no need to enforce the use of the factory method. What needs 
to be enforced is that the program cannot instantiate an instance of 
the cluster base class. This corresponds directly to the C++ case where 
their is no enforcement of a restriction on directly constructing a 
derived concrete class but there is enforcement of the "no 
instantiation of virtual classes" rule.

>   3) Having a private constructor in Ruby doesn't make sense; this is
>      the purpose of a Module (you can always instantiate a Class, but
>      you can't always instantiate a Module)

Having a private constructor makes sense for cluster base classes and 
singleton classes.
> Perhaps if you provide a sample implementation it would be easier to

I'll try and translate my drawing program from ObjC to Ruby.

-- 
Cogito Ergo Spud. - I think therefore I yam.