|
|
|
Perl Modules
Object-oriented Perl
|
What is a module?
|
|
(Summarized from my book, Perl Modules.)
Among the best things with Perl are the huge number of freely available
Perl modules. These modules contain pre-written Perl code that helps
you complete your Perl scripts in a lot less time.
A module provides a way to package Perl code for reuse. There are
hundreds of free modules available on the
Comprehensive Perl Archive Network, or CPAN,
a set of Internet servers located throughout the world.
Available modules include support for access to Oracle and other
databases; networking protocols such as HTTP (Web), POP3 (email),
and FTP (file transfers); and special Win32 modules for access to
the Windows 95 or NT operating systems.
Many modules support object-oriented concepts.
True to Perl's
practical roots, you can create classes and objects without a lot of
fuss. from the perlobj manual entry:
- An object is simply a reference that happens to know which class
it belongs to.
- A class is simply a package that happens to provide methods to
deal with object references.
-
A module is a package that follows certain conventions.
- A method is simply a subroutine that expects an object reference
(or a package name, for class methods) as the first argument.
- An attribute is data inside an object, typically stored in a hash.
|
|
References
|
|
|
References are variables that refer to other variables. References
allow you to access data indirectly, much like a C language pointer,
and are indispensable for objects in Perl.
Perl uses the backslash operator to signify a reference. (This is one more
reason to stick to forward slashes as directory separators on Windows.)
A reference itself is a scalar variable. (This is called a hard reference.)
For example,
$reference = \$var;
The variable $reference now refers to the variable $var.
To get at the value of a reference, you can use the following shorthand syntax:
$v = $$reference;
A reference can point to more than scalar values. You can have
references to lists, hashes and subroutines. For example,
$list_reference = \@list;
@$list_reference = ( 1, 2, 3 );
$hash_reference = \%ENV;
$editor = $$hash_reference{"EDITOR"};
$keys = keys( %$hash_reference);
$subroutine_reference = \&subroutine;
The same rules apply to lists, hashes and subroutines
as for scalars. The $reference is the same as the base part of the list, hash, or subroutine name. For example,
# Subroutine reference.
$subroutine_ref = \&mysub;
&$subroutine_ref(4, 'five');
sub mysub {
my($first, $second) = @_;
print "In my subroutine with $first, $second.\n";
}
# subref.pl
Objects often make use of the arrow operator, ->,
to access elements in an array or hash. For example,
the following array reference statements are equivalent:
$$array_reference[1] = "Second";
$array_reference->[1]= "Second";
The following hash reference statements are also equivalent:
$$hash_reference{"EDITOR"} = "emacs";
$hash_reference->{"EDITOR"} = "emacs";
Most references refer to a named variable. You can also create
a reference to unnamed data, called an anonymous reference.
For example:
$array_reference = [10, 20, 30, 40];
$hash_reference = {
"firstname", "Grover",
"lastname", "Cleveland",
};
$hash_reference = {
"firstname" => "Grover",
"lastname" => "Cleveland",
};
|
|
|
Classes
|
|
|
A class is merely a package that follows the conventions
described here (and in Perl Modules).
There are also a number of online manual entries
that can help quite a lot.
Perl builds up object-oriented
constructs from some rather simple concepts, which you need to
understand to make use of classes in Perl.
A package provides a convenient way for gathering related Perl subroutines
together into a handy bundle. Packages provide a name space, so that your
subroutine and variable names don't interfere with other
subroutines and variables. This provides enough independence that packages
are used to define classes in Perl.
A package starts with the package command and continues until the end of
the enclosing block, or the next package command if the first package is
not inside a block, or the end of the file. You can switch into a package
at any time; packages really only adjust which symbol table is used to look
up identifiers. The default package is called main.
With the package command, you pass the name of the package:
package my_package_name;
A module is a package that follows a few more conventions and is
designed for reuse. First, the files holding modules have names ending
in the .pm extension, short for Perl module.
Modules are normally located in the Perl library directories,
which are listed in the @INC array, such as /usr/lib/perl5 on UNIX or
\PERL\LIB on Windows.
To make use of a module, you typically call the use command with the
name of the module. With use, the Perl interpreter looks in the
directories listed in the @INC array for the module file, assumed to
have a .pm extension. For example, the following command looks for a
file named File.pm in one of directories in @INC (or in one of the
alternative locations listed previously):
use File; # Look for File.pm.
If the module name has a double-colon, this translates to a
subdirectory. Thus, File::Basename refers to a module file called
Basename.pm in the subdirectory named File in one of the directories
in @INC. For example:
use File::Basename; # Look for File/Basename.pm.
On UNIX, this will likely be located in
/usr/lib/perl5/File/Basename.pm. On Windows, this will likely be
\Perl\Lib\File\Basename.pm. The use of the first part of the name,
File, allows you to group similar modules together in the same
subdirectory. For example, File::Basename, File::Copy and File::Find
refer to Basename.pm, Copy.pm, and Find.pm, respectively, in the File
subdirectory in the Perl library. You can nest deeper than a
single directory. Just replace each double-colon with a directory
separator.
A Perl object is merely a reference. To be considered an object, the
reference must be blessed. Blessing a reference allows the object to
know what class it belongs to. A class in Perl is a package that
follows certain conventions.
|
|
|
Constructors
|
|
A constructor is a special subroutine that creates objects
for a given class. While there's no magic behind the name, the
convention is to call the constructor subroutine new. (The
name new is helpful especially for C++ programmers.) Think
of new as creating a new object of that class.
The basic format for a constructor-the new subroutine-follows:
- Initialize a variable for the new object. For example, set
$self to be an anonymous hash.
- Initialize all the data for the object. For example, fill in
values, or the undef value for each attribute in the object.
- Bless the object with the
bless command.
- Return the object.
For example, the following creates a new Account object:
sub new {
#
# $self is an anonymous hash.
#
my $self = {};
#
# Initialize data for this object.
#
$self->{USERNAME} = undef;
$self->{NAME} = undef;
$self->{HOMEDIR} = undef;
$self->{HOMESYSTEM} = undef;
#
# Let the object know its class.
#
bless($self);
return $self;
}
The bless function marks an object-a reference,
remember-with the class the object belongs to. This is
necessary in the constructor for every class. There's
also a two-parameter form of bless that better allows
for inheritance:
bless( $self, $class );
|
|
|
Destructors
|
|
|
You can define a DESTROY routine for your class
that perl will call as your objects are getting
destroyed. Because Perl manages memory for you,
this is not necessary in most cases. But, if you do
define a DESTROY routine, you need to know that perl
does not automatically call the DESTROY routine on an
object's parent class. (C++ calls the equivalent
destructors, so you may have come to expect this
when using object-oriented techniques.)
|
|
|
Methods
|
|
|
A method is just a Perl subroutine. When you use the object-based call
to a subroutine, such as $object->method(), you are still calling a
standard Perl subroutine. The key hidden detail is that the object
(really a reference) is passed as the first parameter to the
subroutine. That is, these two forms are essentially identical:
$object->method( $parameters );
method $object $parameters;
It's just easier and more "object-oriented" to use the
$object->method() approach, because it appears as if you're calling
the subroutine method on the given object.
When you write methods, you're writing Perl subroutines. The only
thing special is that the first parameter to the subroutine will
be the object itself (which is a reference). All other parameters
work as you'd expect.
For example, the following is a method that works on objects
of class Account:
#
# Debugging methods.
#
sub print {
# First parameter is the object itself.
my $self = shift;
print "User: $self->{NAME}\n";
print "User name: $self->{USERNAME}\n";
print "Home machine: $self->{HOMESYSTEM}\n";
print "Home directory: $self->{HOMEDIR}\n";
}
|
|
|
Attributes
|
|
|
Since Perl objects are blessed references, attributes are any
data that the reference refers to. For example, most Perl classes
use a hash for holding the object's data, the attributes.
With this, you can refer to the attributes directly from
Perl's reference syntax, usually with the -> operator:
$self->{NAME} = "Fred";
You can also write data access methods, such as the following:
sub name {
my $self = shift;
#
# If there are any arguments left, then set value.
#
if (@_) {
$self->{NAME} = shift;
}
return $self->{NAME};
}
If you call the name method without any parameters (not counting the
object that Perl places as the first parameter), then the name routine
returns the value held in the hash with the NAME key. If you pass a
parameter, then the name routine sets the value at the NAME key
to the parameter you passed in.
|
|
|
Example class
|
|
The following shows a very simple example class, called Account.
Objects of this class could hold information on a user account.
#
# User login account class.
#
package Account;
#
# Constructor.
#
sub new {
#
# $self is an anonymous hash.
#
my $self = {};
#
# Initialize data for this object.
#
$self->{USERNAME} = undef;
$self->{NAME} = undef;
$self->{HOMEDIR} = undef;
$self->{SYSTEM} = undef;
#
# Let the object know its class.
#
bless($self);
return $self;
}
#
# Destructor.
#
sub DESTROY {
print "Argh. Life was sweet.\n";
}
#
# Data-access methods.
# You can pass a parameter, in which case
# the attribute gets set to the new value.
# If you skip the parameter, the value is
# returned.
#
sub username {
#
# Extract first parameter--the object ref.
#
my $self = shift;
#
# If there are any arguments left, then set value.
#
if (@_) {
$self->{USERNAME} = shift;
}
return $self->{USERNAME};
}
sub name {
my $self = shift;
#
# If there are any arguments left, then set value.
#
if (@_) {
$self->{NAME} = shift;
}
return $self->{NAME};
}
sub homedir {
my $self = shift;
#
# If there are any arguments left, then set value.
#
if (@_) {
$self->{HOMEDIR} = shift;
}
return $self->{HOMEDIR};
}
sub homesystem {
my $self = shift;
#
# If there are any arguments left, then set value.
#
if (@_) {
$self->{HOMESYSTEM} = shift;
}
return $self->{HOMESYSTEM};
}
#
# General methods.
#
#
# Create a new user account. This is probably
# the main reason to use this class.
#
sub create {
# Fill in with code for UNIX or Windows NT.
}
#
# Debugging methods.
#
sub print {
my $self = shift;
print "User: $self->{NAME}\n";
print "User name: $self->{USERNAME}\n";
print "Home machine: $self->{HOMESYSTEM}\n";
print "Home directory: $self->{HOMEDIR}\n";
}
# By convention, end a package file with 1,
# so the use or require command succeeds.
1;
# Account.pm
Note the package command at the beginning of this script, as well as
the 1; at the end. This is standard for Perl modules.
Name this file Account.pm. Then, you can access Account objects
using the following script as a guide:
#
# Use Account class.
#
use Account;
#
# Create new object.
#
$account = new Account;
#
# Set data into object.
#
$account->username("erc");
$account->homedir("/usr2/erc");
$account->homesystem("yonsen");
$account->name("Eric Foster-Johnson");
# Print out object data.
$account->print;
# useacnt2.pl
You now have your first class. Notice the use command and the way the
script calls methods on the object.
|
|
|
Inheritance
|
|
|
Creating one class usually begets another. And another.
Once you have a number of classes, you start to notice
similarities between them.
Inheritance is the ability for one class to reuse methods
defined in another class. Inheritance allows multiple classes to
share common code. In most cases, a parent or base class provides
general functionality, and a child class provides specialized
extensions to the general functionality.
For example, an Company::Employee works for a company
and can expect to get paid for that work. A Company::Manager
is a Company::Employee. A Company::Manager works for a company,
gets paid for that work, and can also make silly decisions. In
object-oriented terminology, a Company::Manager inherits from
Company::Employee, or a Company::Manager is a specialized class
derived from Company::Employee.
Like with most object-oriented topics, Perl exposes some
of its implementation when you try to inherit from other classes.
At its basic level, the key points include:
- Perl only supports method inheritance, not attribute inheritance,
but there are clever ways around this limitation.
- The @ISA array names the classes your class derives from.
- Module names have nothing to do with inheritance.
- Your constructors need to call the two-parameter form of bless
to allow for inheritance
The @ISA array holds the list of the classes that your class inherits
from. For example:
# Simple class inherits everything.
package Company::GroupManager;
use Company::Manager;
@ISA = qw(Company::Manager );
1;
# GroupManager.pm
This example states that a Company::GroupManager is a
Company::Manager. That is, a Company::GroupManager inherits
from Company::Manager. Note that Company::GroupManager defines
no methods, so all methods are inherited from Company::Manager.
While you can actually make classes like this, there is little point.
The purpose of this short example is to show the @ISA array.
When you try to execute a method that a particular class doesn't
define, the perl command looks to the list of classes (packages)
in the @ISA array.
Each class in the @ISA array is searched in order. For each class,
perl searches that class' @ISA array before going on to the next
class in your package's @ISA array, for a depth-first search. The perl
interpreter executes the first matching subroutine.
If all the classes in the @ISA array (and all their parent classes),
then perl looks for a method called AUTOLOAD, which is given an
attempt to execute the method. Autoloading allows you to only
load and parse the subroutines used, rather than load everything from
a potentially large library.
In the Company::GroupManager example shown previously,
the Company::GroupManager class does not define a constructor,
the new subroutine. You can still call new to create a Company::GroupManager
object, though, so long as one of the classes Company::GroupManager
inherits from, in this case Company::Manager, or one of the classes
manager inherits from, defines a method named new. To work properly,
this new method must call the two-parameter form of bless.
With this, the typical new routine looks as follows:
sub new {
my($class) = shift;
my($self) = {};
bless( $self, $class );
return $self;
}
This form of the constructor makes things better for inheritance,
The main idea is that the class of the object created may not be
the class passed in to the new subroutine. (It may be a derived
class, Company::GroupManager, for example.)
If your class defines a method, and the parent class
defines a method of the same name, then objects of your
class will call the method on your class.
|
|
|
Deconstructing modules
|
|
|
To help gain a better idea of how to put together a
module, the following example deconstructs a small module
with comments for the special Perl conventions:
#
# Sample module with explanation.
#
package Company::Manager;
# We've named our class, and avoiding using
# a top-level name. Presumably, this class is
# related to other classes in the Company::
# hierarchy.
use strict;
# The strict pragma enforces more rules.
# See Chapter 10.
use vars qw($VERSION @ISA @EXPORT_OK);
# Strict can sometimes be too strict, so the vars
# pragma allows for certain variables to be free
# of strict's rules.
use Company::Employee;
# Include code for Company::Employee, since this
# class inherits from it.
use Exporter;
# Include code for Exporter, since this class
# inherits from it.
@ISA = qw( Company::Employee Exporter );
# @ISA defines which classes our class inherits from,
# Company::Employee and Exporter.
$VERSION = '1.00';
# All classes should provide a version number to
# allow for version checking and to differentiate
# new and potentially incompatible versions.
@EXPORT_OK = qw( find_manager );
# This class does not export any symbols by default
# (that would be in @EXPORT). Instead, we export
# find_manager only on demand.
#
# Constructor for Company::Manager objects.
#
sub new {
my($param) = shift;
my($class) = ref($param) || $param;
# Handle class name or object as first parameter.
my($self) = {};
# Initialize data as an empty hash.
bless( $self, $class );
# Bless reference into class.
# Initialize attributes for this class.
if (@_) {
my($name) = @_;
$self->{NAME} = $name;
# We set one attribute.
} else {
$self->{NAME} = undef;
}
# ...
return $self;
# Return object reference.
}
#
# Data-access method.
#
sub Name {
my($self) = shift;
#
# If there are any arguments left, then set value.
#
if (@_) {
$self->{NAME} = shift;
}
return $self->{NAME};
}
#
# This is not a method. Pass a manager name
# to look up a record for that manager.
#
sub find_manager {
my($manager_name) = $_[0];
# If found, return new manager.
# This example just pretends to look things up.
return Company::Manager->new( $manager_name );
}
1; # Ensure success with use or require command.
# Manager.pm
Don't expect to get everything all at once. Just keep trying and
things should work.
|
|
|
Creating modules automatically
|
|
|
Perl comes with a standard utility called h2xs, which
you can use to automatically create a barebones module .pm
file, as well as a number of files useful for debugging and
installation.
Originally created to help create code to glue C-language
extensions onto Perl, you can use h2xs to create all-Perl modules as well.
The basic h2xs command follows:
h2xs -X -n module_name
The -X option tells h2xs to skip the C-language glue it
normally outputs. Use the -X option whenever you're creating
a module written entirely in Perl. The -n option is followed
by the name of the module. For example,
h2xs -X -n User::Account
This command creates the following files for a new module
called User::Account:
User/Account/Account.pm
User/Account/Makefile.PL
User/Account/test.pl
User/Account/Changes
User/Account/MANIFEST
|
|
|
Installing modules
|
|
|
When you download a Perl module from CPAN, you first need to
uncompress the files. Most modules are UNIX tar archives
compressed using the GNU Zip program, gzip.
The basic UNIX commands to uncompress and extract the files
from a module bundle are something like the following:
gunzip MyModule-0.01.tar.gz
tar xvof MyModule-0.01.tar
On Windows, you can use a modern ZIP program, such as WinZip. These
programs understand UNIX tar archives and the GNU Zip compression
format.
Once you've extracted the files that make up a module, the next
step is to install the module.
The following commands apply to virtually every module:
perl Makefile.PL
make
make test
make install
On Windows, you can run the same commands from an MS-DOS
prompt, except that you need to run dmake instead of
make.
Most modules come with a file named README. I even saw
one module with a file named README_OR_DIE. If you haven't
caught on yet, you're supposed to read the file. The README
file should explain any other software you need for a given module,
such as other modules, Oracle programming libraries,
particular versions of operating systems, and so on.
|
|
|
For more on modules
|
|
|
Perl includes a lot of online information in the form
of UNIX man pages or HTML files (on Windows). The following
topics help with writing modules:
| Subject |
Documentation Topic |
| Modules |
perlmod, perlmodlib, perlsub |
| Classes and objects |
perlref, perlobj, perltoot, perlbot |
| Tying hashes |
perltie |
| Linking with C |
perlcall, perlembed, perlguts, perlxs, perlxstut |
| Inter-process communication |
perlipc |
In addition, each module should provide documentation that
you can access from the perldoc command, for example:
perldoc Net::Ping
My book, Perl Modules,
provides an in-depth explanation for how to create modules,
as well as how to use many of the available Perl modules.
Look on any CPAN (Comprehensive Perl Archive Network) site for a full listing
of Perl modules. You can view the listing by name, author, category,
etc.:
-
Cool Modules List
-
http://www.perl.com/CPAN-local/modules/01modules.index.html
-
http://www.perl.com/CPAN-local/modules/00modlist.long.html
-
http://www.perl.com/CPAN-local/modules/by-module/
-
http://www.perl.com/CPAN-local/modules/by-category/
-
http://www.perl.com/CPAN-local/modules/by-authors/
The frequently-asked questions, or FAQ, list for Perl is located at
Perl FAQ.
Chances are that any problem you face has
been faced by others, and there may even be an answer in this document.
To supplement the Perl FAQ, you can see
http://www.perl.com/CPAN/doc/FMTEYEWTK/index.html. This document,
called Far More Than Everything You've Ever Wanted to Know About...,
provides just that in a collection of various topics on Perl.
The Perl Module Mechanics page, at
http://world.std.com/~swmcd/steven/perl/module_mechanics.html,
provides a short tutorial on creating modules, classes, and objects.
The LWP library home page is located at
http://www.linpro.no/lwp/.
The DBI, or database interface, suite of modules includes means
to access Oracle, Informix, Sybase, and many other database
systems. The DBI module itself provides a generic interface to
access databases. You need to pair DBI with a DBD, short for
database driver, module, such as DBD::Oracle.
The DBI home page contains a lot of useful information, including
examples and frequently-asked questions
http://www.symbolstone.org/technology/perl/DBI/.
(Note that the old link was
http://www.hermetica.com/technologia/DBI.)
|
|
|
|
|