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:
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.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: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.
{ 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
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |