Welcome to dynamic language world, where the land
moves out from under your feet.
Use CGI::Simple. A lot of magic and trickery conflicts
in Perl. Even after it is fixed, new magic and trickery
will conflict. Not everything will always work with
everything else. Tieing has a long history of conflicts
and still has some caveats.
can() itself is typical - a static language would know
at compile time whether or not a method exists in a class.
No run time test is needed. Not only can methods appear
due to AUTOLOAD, classes might act as generators of
sort, creating methods by binding closures to data and
assigning them names as a sort of template.
Some classes act as object black holes, where all method
calls are errors. Other as white holes, where all method
calls silently return.
And numerous other things.
Parrot plans to add to isa() and can() a has() to
test attributes. This compounds the problem - ineffectual
tools can sometimes distract you from real solutions.
If you want to play the object game, use interfaces.
Both isa() and can() share a common problem that stems
from their run time nature: they encourage
explicit type case analysis. Any conditional logic
that depends on which class you have should be part
of the class itself. Otherwise, each new class introduced
breaks things. C has for a long time checked that switch()
statements when used on enum values check for each possible
enum value and warn otherwise. This is the same problem
with a different solution - introducing new values
shouldn't break old code. It takes some object-think
to get into the mode of shuffling code into objects
so that objects respond how they like when a
certain kind of thing is desired.
Objects should respond to general requests rather than
specific demands. If you're thinking in terms of
adding to a counter using an accessor, you're thinking
wrong. Think different. Instead, think of notifying
of arrival of email or whatever you were counting.
The object may count it as originally intended, or it
might present a
event listerns interface to broadcast notifications.
Or perhaps other things. Anyway, remember, use methods
as a way of notifying objects of information or event,
not demanding that something be done, especially not
demanding it be done a certain way.
Perl lets you extend classes after the fact by
revisiting namespaces. B::Generate, for instance,
extends B to make the accessors put/get instead of merely
get. Obviously B couldn't be extended in two seperate
ways at the same time, but remember that you're still
in the dynamic language world. Adding new methods is
safer. Safer still is
super class abstraction, where the root class is
the most general case of objects of that type.
Dynamic languageism is the heart of the matter. You
can skirt it in these different ways, some more elegant
than others, some more appropriate, but Grace Hopper's
ghost will raise from the grave and haunt you for 24 hours
if you keep doing things the way you've always done
them for the reason that you've always done them that
way. To make sure that only the correct types can
possibily worm their way to where they're expected
exclusive of everything else, use
strict type checking. Don't panic! You don't turn
all dynamicism off, it is done on a method by method,
variable by variable basis. Perl can inspect your code
and warn if there is a possibility that something other
than a CGI object or some subclass will arrive at a place where you only want a CGI object. With a few caveats
(things missing from the typesafety module), any warnings
generated represent a design short coming in your program
from an object oriented perspective. No, objects aren't
like guns where any 5 year old can just pick it up and
use it. The language features that support objects are
less than half of the battle. Knowing how to use them
is far more important. Few people write good object
oriented Perl but many large fine C programs written with
a good grasp of objects exist - Postgres, the Linux
kernel, MySQL, Apache.
Dynamic languages are powerful, but when the question
comes to sanity, structure, and order, a bit of the
static might be just what the doctor ordered.
Everything in its time in place - preferably all at the
same time under Perl though =)
-scott
P.S.: I'm not a regular reader and I'm not one for
discussions. Reply to this, of course, but if you want
to get my attention, please email me - scott@slowass.net.
Thanks.