Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

chromatic (983)

chromatic
  (email not shown publicly)
http://wgz.org/chromatic/

Blog Information [technorati.com] Profile for chr0matic [technorati.com]

Journal of chromatic (983)

Wednesday January 15, 2003
08:29 PM

Class::Interface

[ #10002 ]

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.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • Interesting stuff. Wouldn't it be easier to just override isa() though? For example, if I want to tell the world that I implement 'Viewable', then I could do:

      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 in

    • Yes, you could override isa(), or much about with the appropriate @ISA. However, per the example in the docs, an Airport is not an Arcade. The Airport has an Arcade. Surprisingly, the semantic distinction is important to me.

      • 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

        • 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 s

  • Which was my attempt at adding interface support some time back. And which I've since abandoned as I've become convinced that I like optimistic typing a lot thank you very much and that, even though Perl 6 will give you the ability to specify an argument's type, in general you shouldn't bother unless there's evidence that doing so will help things go a lot faster.
    • 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 the Dog interface, and it has the doglike methods from A

  • Hi, did you think about an (optional) compile time check of interface implementation using a CHECK block? The module is nice, however, I'd rather have something with the expressiveness of Class::Contract for interfaces, that lets you defined pre-, postconditions and invariants for methods; and a pony.
  • I'm seriously considering adding support for this into the Parrot core, though I don't know that anything will actually use it. It seems to me that most OO inheritance things aren't really is or has relationships (though they are both useful) but does relationships--presentations of guaranteed interfaces/protocols/method sets. I mean, who really cares if you're a sub-class of hash, or array, or frob, as long as you present the base hash or array or frob methods?
    • 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.)

      • 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.