I should start by admitting to being a co-author and the currenty maintainer of Class::Prototyped, so I'm a bit biased!

My general rule of thumb is that I use C::P when I'm in a situation where someone using the module I'm writing would either need to do one of two things:

This tends to be the generation of what I call behavioral objects (if there is a proper pattern name for this, please let me know:). Examples are objects that interface with database records (all sorts of validation and stuff), objects that interface with individual fields on a database record (even more validation:), etc. Imagine if you had to create a separate class for every field on every table in your database. If you don't do that, though, you're in a world where you pass all these anonymous subroutines as parameters, you've got to write code to implement inheritance yourself, etc., etc. Yeach!

I frequently try to avoid using C::P because I don't want to increase the barrier to usage for modules I'm releasing, but before long I realize that I'm just reinventing the wheel and that there's a reason Ned and I developed C::P! So I bite the bullet, start using it, and suddenly everything starts clearing up.

Now, time for the obligatory sales portion!

C::P is designed to address many of the concerns like those raised by Corion. Quoting from the (rather voluminous) docs:

In Self, everything is an object and there are no classes at all. Perl, for better or worse, has a class system based on packages. We decided that it would be better not to throw out the conventional way of structuring inheritance hierarchies, so in Class::Prototyped, classes are first-class objects.

However, objects are not first-class classes. To understand this dichotomy, we need to understand that there is a difference between the way "classes" and the way "objects" are expected to behave. The central difference is that "classes" are expected to persist whether or not that are any references to them. If you create a class, the class exists whether or not it appears in anyone's @ISA and whether or not there are any objects in it. Once a class is created, it persists until the program terminates.

Objects, on the other hand, should follow the normal behaviors of reference-counted destruction - once the number of references to them drops to zero, they should miraculously disappear - the memory they used needs to be returned to Perl, their DESTROY methods need to be called, and so forth.

What this means is that you should use C::P in such a way that things that are classes get class names. Then people like Corion can easily do things like:

{ my $called; WWW::Mechanize->reflect->addSlot(get => sub { $called++; }); ok( $shell->foo() ); is( $called, 1, '$shell->agent->get was called one time'); }

I think the single greatest insight that Ned and I had was providing a unified OO interface for mucking about with the structure of classes that applies both to C::P created classes and to those written without any knowledge of C::P! The other cool thing about C::P is that because it uses all of the normal Perl class mechanisms (when it creates objects, it creates a new class), you get access to all of the normal Perl behavior, including multiple inheritance. There is no overhead to C::P except for object instantiation (which can be avoided if you want dumb leaf nodes by providing your own new method) and the normal Perl method call overhead. Unless you are using slot attributes, in which case there is the normal Perl subroutine call overhead (different from method overhead in that there is no need to find the implementatation).

Some of the cool features, like slot attributes, are only accessible if you buy into the whole C::P approach, but it's relatively easy to mix and match the C::P approach with more traditional Perl approaches, especially once you grok the few underlying concepts. I will be the first to admit that I've done an incredibly poor job of selling C::P to the community, but part of that is because, independent of time constraints, I don't really know where to start.

OK, enough blathering.

--Toby Ovod-Everett


In reply to Re: When to use prototype inheritence? by tovod-everett
in thread When to use prototype inheritence? by bsb

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.