=head1 NAME
perltooc - Tom's OO Tutorial for Class Data in Perl
=head1 DESCRIPTION
When designing an object class, you are sometimes faced with the situation
of wanting common state shared by all objects of that class.
Such I act somewhat like global variables for the entire
class, but unlike program-wide globals, class attributes have meaning only to
the class itself.
Here are a few examples where class attributes might come in handy:
=over 4
=item *
to keep a count of the objects you've created, or how many are
still extant.
=item *
to extract the name or file descriptor for a logfile used by a debugging
method.
=item *
to access collective data, like the total amount of cash dispensed by
all ATMs in a network in a given day.
=item *
to access the last object created by a class, or the most accessed object,
or to retrieve a list of all objects.
=back
Unlike a true global, class attributes should not be accessed directly.
Instead, their state should be inspected, and perhaps altered, only
through the mediated access of I. These class attributes
accessor methods are similar in spirit and function to accessors used
to manipulate the state of instance attributes on an object. They provide a
clear firewall between interface and implementation.
You should allow access to class attributes through either the class
name or any object of that class. If we assume that $an_object is of
type Some_Class, and the &Some_Class::population_count method accesses
class attributes, then these two invocations should both be possible,
and almost certainly equivalent.
Some_Class->population_count()
$an_object->population_count()
The question is, where do you store the state which that method accesses?
Unlike more restrictive languages like C++, where these are called
static data members, Perl provides no syntactic mechanism to declare
class attributes, any more than it provides a syntactic mechanism to
declare instance attributes. Perl provides the developer with a broad
set of powerful but flexible features that can be uniquely crafted to
the particular demands of the situation.
A class in Perl is typically implemented in a module. A module consists
of two complementary feature sets: a package for interfacing with the
outside world, and a lexical file scope for privacy. Either of these
two mechanisms can be used to implement class attributes. That means you
get to decide whether to put your class attributes in package variables
or to put them in lexical variables.
And those aren't the only decisions to make. If you choose to use package
variables, you can make your class attribute accessor methods either ignorant
of inheritance or sensitive to it. If you choose lexical variables,
you can elect to permit access to them from anywhere in the entire file
scope, or you can limit direct data access exclusively to the methods
implementing those attributes.
=head1 Class Data in a Can
One of the easiest ways to solve a hard problem is to let someone else
do it for you! In this case, Class::Data::Inheritable (available on a
CPAN near you) offers a canned solution to the class data problem
using closures. So before you wade into this document, consider
having a look at that module.
=head1 Class Data as Package Variables
Because a class in Perl is really just a package, using package variables
to hold class attributes is the most natural choice. This makes it simple
for each class to have its own class attributes. Let's say you have a class
called Some_Class that needs a couple of different attributes that you'd
like to be global to the entire class. The simplest thing to do is to
use package variables like $Some_Class::CData1 and $Some_Class::CData2
to hold these attributes. But we certainly don't want to encourage
outsiders to touch those data directly, so we provide methods
to mediate access.
In the accessor methods below, we'll for now just ignore the first
argument--that part to the left of the arrow on method invocation, which
is either a class name or an object reference.
package Some_Class;
sub CData1 {
shift; # XXX: ignore calling class/object
$Some_Class::CData1 = shift if @_;
return $Some_Class::CData1;
}
sub CData2 {
shift; # XXX: ignore calling class/object
$Some_Class::CData2 = shift if @_;
return $Some_Class::CData2;
}
This technique is highly legible and should be completely straightforward
to even the novice Perl programmer. By fully qualifying the package
variables, they stand out clearly when reading the code. Unfortunately,
if you misspell one of these, you've introduced an error that's hard
to catch. It's also somewhat disconcerting to see the class name itself
hard-coded in so many places.
Both these problems can be easily fixed. Just add the C