On Jul 24, chromatic wrote:
> On Thursday, July 24, 2003, at 05:28 PM, Benjamin Goldberg wrote:
> >If this were Java, the way to do this would be to define a Thingie
> >interface, and then an (archetypical) ThingieObject class... any time
> >that we want to actually *create* Thingies, we would use "new
> >ThingieObject", but everywhere else, we would use the typename
> >"Thingie".  This way, when we want a class which "acts like" a Thingie,
> >but without inheriting any of it's innards, simply implement the 
> >Thingie
> >interface, instead of inheriting the ThingyObject class.
> 
> Yes, that's the Java way to do it.  Surely we can do it better in Perl 
> 6.
> 
> The problem with Java interfaces is that you have to rely on the 
> library writer to have expected you to use an interface.  Given the 
> amount of CPAN modules that, for example, expect a glob and preclude me 
> from passing in an IO::Handle with code like this:
> 
>       croak "Need a glob" unless ref $thingie eq 'GLOB';
> 
> I'm not sure that the Java style is helpful.  I'd rather not multiply 
> entities needlessly.
> 
> >For our "isa" operator, and (perhaps more importantly) for
> >multimethod dispatch and/or sub prototype checking, we only check if an
> >object inherits from a class's magic parent interface, and *don't* 
> >check
> >if it *really* inherits from that class itself.
> 
> <heretic>
> Why should an implementor inherit from the interface?
> 
> If inheritance and polymorphic equivalence are two different things, 
> they ought to be handled two different ways.  If anything, inheritance 
> is a specific case of the general mechanism of marking polymorphic 
> equivalence.
> 
> Again, the interesting question isn't "Does this thing derive from 
> something I know about?" It's "Does this thing support the operations I 
> expect it to support?  I don't care how, just that it does."
> 
> I don't want to call $mock_foo->isa( 'foo' ) because $mock_foo *isn't* 
> a foo.  I don't want to call $delegates_to_foo->isa( 'foo' ) because 
> $delegates_to_foo *isn't* a foo.  They can both handle foo-methods, but 
> neither is a foo.
> </heretic>

    My two cents:  the best possible use of an interface/protocol is
to define a set of methods *and their semantics*, and *not* their
implementation.  In pseudocode:

        protocol Window {
            method print;
            method close;
            method bringToFront;
        }

        class MyWindow:  implements Window;

    You're saying that MyWindow has print, close, and bringToFront
methods.  You're not saying whether they're inherited, or implemented
from scratch.  You *are* saying that close() will erase a graphical
rectangle on a display, not disconnect a filehandle or return "true"
if it's nearby.

    So the useful feature of this abstraction is that, given an
anonymous object, you don't ask, "do you implement method called
so-and-so", e.g., "$anon->can('print')"; you ask it, "do you do the
things that a Window does," e.g., "$anon->implements('Window')".

    So a class shouldn't inherit from an interface.  It should
assert that it implements it.

    - Kurt

Reply via email to