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