I'm not a language purist by any means. I consider myself pragmatic, but realize I'm often idealistic. It's hard to reconcile those two ideas, though.
Consider polymorphism. I've most often seen it explained in terms of inheritance. I'm not a big fan of strong typing in general (at least as C and its descendants do it), but mixing polymorphism with the typing system seems... really wrong. Part of the reason Test::MockObject works is because polymorphism isn't limited to objects that share a common ancestor.
The secret is, objects which share a common interface are isomorphic.
Okay, it's not a very well-kept secret. Still, I've seen (and written) too much Perl code that relies on isa()
. (Hey, at least I'm way over checking ref()
so often!)
I'd like to see that Perl 6 doesn't encourage falling into that trap. At least, I'd like to see that Perl 6 encourages composition and delegation as well as it encourages inheritance. (Having failed to convince Allison completely through mad rhetorical skills, I resorted to code.)
In that light, I present Class::Interface. Please see the discussion at Perl Monks for more information.
As always, I may be way off track here. Once I figured out the way things really ought to work, though, they made a great deal more sense.
sub isa {
my ($self, $pkg) = @_;
return 1 if $pkg eq 'Viewable';
return 1 if grep { $_->isa($pkg) } @ISA;
return 0;
}
On the other hand, by writing a new module you could implement some useful stuff that Perl's OO left out, like compile-time checking of interfaces. For example, if I create an interface called 'Viewable' that requires methods called 'view' and 'hide' then Class::Interface could make sure my class can('view') and can('hide') at compile-time.
-sam
Re:Looks interesting, but...
chromatic on 2003-01-16T06:00:09
Yes, you could override
isa()
, or much about with the appropriate@ISA
. However, per the example in the docs, anAirport
is not anArcade
. TheAirport
has anArcade
. Surprisingly, the semantic distinction is important to me.Re:Looks interesting, but...
samtregar on 2003-01-16T06:13:45
Isn't the choice of inheritence or composition an implementation detail that should be private to the class? What kind of use case do you have where a caller needs to know whether an interface is implemented using inheritence or composition?-sam
Re:Looks interesting, but...
chromatic on 2003-01-16T07:55:32
That's exactly the point! Good thinking.
:) Using
isa()
dictates that the implementation is inheritance (or, at least, that you have to fake up that you're inheriting).In Class::Interface, derived classes are automatically marked as implementing their parent class interfaces. Whether you inherit or not, by talking about interfaces instead you're saying "objects of this class can (or should) handle the messages an object of this type can". You just have to be a little more explicit if you're not subclassing.
Re:Have you seen ex::interface?
chromatic on 2003-01-16T17:53:50
I didn't catch it on my first foray through the CPAN. Now that I've seen it, I see it does something I wanted to avoid.
One of my goals is to support mixins without giving up the possibility of having interface checking. One can imagine a module that provides mixins that, grouped together, form a named interface. Mixing them into a class is simple:
package RobotDog; use Animals mixin => ':Dog';
RobotDog
would now be marked as implementing theDog
interface, and it has the doglike methods fromAnimals
. Any code that wants to check that it's dealing with a Doglike object should check that the object implementsDog
.I don't expect often to check typing in order to make my program go faster. I expect to do it to verify that my methods have the proper arguments. Certainly multimethods will help, but I'll lament the lack of much power and flexibility if argument type checking is limited to inheritance.
Re:Might slip in...
chromatic on 2003-01-20T03:41:02
The nice part about does is that if you get it right, you get is for (almost) free! (That's assuming
Class::Interface
does it correctly, anyway.)Re:Might slip in...
Elian on 2003-01-20T04:24:28
True, but core support certainly doesn't hurt.:) Besides, having one low-level way to do it makes it more likely that languages layering on top of Parrot are going to use the common infrastructure, and that makes interoperability much nicer.