📄 ch4.htm
字号:
<HTML>
<HEAD>
<TITLE>Chapter 4 -- Introduction to Perl Modules</TITLE>
<META NAME="GENERATOR" CONTENT="Mozilla/3.0b5aGold (WinNT; I) [Netscape]">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#CE2910">
<H1><FONT COLOR=#FF0000>Chapter 4</FONT></H1>
<H1><B><FONT SIZE=5 COLOR=#FF0000>Introduction to Perl Modules</FONT></B>
</H1>
<P>
<HR WIDTH="100%"></P>
<P>
<H3 ALIGN=CENTER><FONT COLOR="#000000"><FONT SIZE=+2>CONTENTS<A NAME="CONTENTS"></A>
</FONT></FONT></H3>
<UL>
<LI><A HREF="#WhatIsaPerlModule" >What Is a Perl Module?</A>
<LI><A HREF="#UsingPerlModulesusevsrequire" >Using Perl Modules: use vs. require</A>
<LI><A HREF="#TheSampleLetterpmModule" >The Sample Letter.pm Module</A>
<LI><A HREF="#SubroutinesandPassingParameters" >Subroutines and Passing Parameters</A>
<LI><A HREF="#AnotherSampleModuleFinance" >Another Sample Module: Finance</A>
<UL>
<LI><A HREF="#ReturnedValuesfromSubroutinesinaPa" >Returned Values from Subroutines in a Package</A>
</UL>
<LI><A HREF="#MultipleInheritance" >Multiple Inheritance</A>
<LI><A HREF="#ThePerlModuleLibraries" >The Perl Module Libraries</A>
<UL>
<LI><A HREF="#ExtensionModules" >Extension Modules</A>
<LI><A HREF="#WhatIsCPAN" >What Is CPAN?</A>
</UL>
<LI><A HREF="#Summary" >Summary</A>
</UL>
<HR>
<P>
This chapter introduces you to the concepts behind references
to Perl modules, packages, and classes. It also shows you how
to create a few sample modules.
<H2><A NAME="WhatIsaPerlModule"><FONT SIZE=5 COLOR=#FF0000>What
Is a Perl Module?</FONT></A></H2>
<P>
A Perl module is a set of Perl code that acts like a library of
function calls. The term <I>module</I> in Perl is synonymous with
the word <I>package</I>. Packages are a feature of Perl 4, whereas
modules are prevalent in Perl 5.
<P>
You can keep all your reusable Perl code specific to a set of
tasks in a Perl module. Therefore, all the functionality pertaining
to one type of task is contained in one file. It's easier to build
an application on these modular blocks. Hence, the word <I>module</I>
applies a bit more than <I>package</I>.
<P>
Here's a quick introduction to modules. Certain topics in this
section will be covered in detail throughout the rest of the book.
Read the following paragraphs carefully to get an overview of
what lies ahead as you write and use your own modules.
<P>
What is confusing is that the terms <I>module</I> and <I>package</I>
are used interchangeably in all Perl documentation, and <I>these
two terms mean the very same thing</I>. So when reading Perl documents,
just think "package" when you see "module"
and vice versa.
<P>
So, what's the premise for using modules? Well, modules are there
to package (pardon the pun) variables, symbols, and interconnected
data items together. For example, using global variables with
very common names such as <TT><FONT FACE="Courier">$k</FONT></TT>,
<TT><FONT FACE="Courier">$j</FONT></TT>, or <TT><FONT FACE="Courier">$i</FONT></TT>
in a program is generally not a good idea. Also, a loop counter,
<TT><FONT FACE="Courier">$i</FONT></TT>, should be allowed to
work independently in two different portions of the code. Declaring
<TT><FONT FACE="Courier">$i</FONT></TT> as a global variable and
then incrementing it from within a subroutine will create unmanageable
problems with your application code because the subroutine may
have been called from within a loop that also uses a variable
called <TT><FONT FACE="Courier">$i</FONT></TT>. The use of modules
in Perl allows variables with the same name to be created at different,
distinct places in the same program.
<P>
The symbols defined for your variables are stored in an associative
array, referred to as a <I>symbol table</I>. These symbol tables
are unique to a package. Therefore, variables of the same name
in two different packages can have different values.
<P>
Each module has its own symbol table of all symbols that are declared
within it. The symbol table basically isolates synonymous names
in one module from another. The symbol table defines a <I>namespace</I>,
that is, a space for independent variable names to exist in. Thus,
the use of modules, each with its own symbol table, prevents a
variable declared in one section from overwriting the values of
other variables with the same name declared elsewhere in the same
program.
<P>
As a matter of fact, all variables in Perl belong to a package.
The variables in a Perl program belong to the <TT><FONT FACE="Courier">main</FONT></TT>
package. All other packages within a Perl program either are nested
within this main package or exist at the same level. There are
some truly global variables, such as the signal handler array
<TT><FONT FACE="Courier">%SIG</FONT></TT>, that are available
to all other modules in an application program and cannot be isolated
via namespaces. Only those variable identifiers starting with
letters or an underscore are kept in a module's symbol table.
All other symbols, such as the names <TT><FONT FACE="Courier">STDIN</FONT></TT>,
<TT><FONT FACE="Courier">STDOUT</FONT></TT>, <TT><FONT FACE="Courier">STDERR</FONT></TT>,
<TT><FONT FACE="Courier">ARGV</FONT></TT>, <TT><FONT FACE="Courier">ARGVOUT</FONT></TT>,
<TT><FONT FACE="Courier">ENV</FONT></TT>, <TT><FONT FACE="Courier">Inc</FONT></TT>,
and <TT><FONT FACE="Courier">SIG</FONT></TT> are forced to be
in package <TT><FONT FACE="Courier">_main.</FONT></TT>
<P>
Switching between packages affects only namespaces. All you are
doing when you use one package or another is declaring which symbol
table to use as the default symbol table for lookup of variable
names. Only dynamic variables are affected by the use of symbol
tables. Variables declared by the use of the <TT><FONT FACE="Courier">my</FONT></TT>
keyword are still resolved with the code block they happen to
reside in and are not referenced through symbol tables. In fact,
the scope of a package declaration remains active only within
the code block it is declared in. Therefore, if you switch symbol
tables by using a package within a subroutine, the original symbol
table in effect when the call was made will be restored when the
subroutine returns.
<P>
Switching symbol tables affects only the default lookup of dynamic
variable names. You can still explicitly refer to variables, file
handles, and so on in a specific package by prepending a <TT><I><FONT FACE="Courier">packageName</FONT></I><FONT FACE="Courier">::</FONT></TT>
to the variable name. You saw what a <I>package context</I> was
when using references in <A HREF="ch3.htm" tppabs="http://www.mcp.com/815097600/0-672/0-672-30891-6/ch3.htm" >Chapter 3</A>. A package
context simply implies the use of the symbol table by the Perl
interpreter for resolving variable names in a program. By switching
symbol tables, you are switching the package context.
<P>
Modules can be nested within other modules. The nested module
can use the variables and functions of the module it is nested
within. For nested modules, you would have to use <TT><I><FONT FACE="Courier">moduleName</FONT></I><FONT FACE="Courier">::<I>nestedModuleName</I></FONT></TT>
and so on. Using the double colon (<TT><FONT FACE="Courier">::</FONT></TT>)
is synonymous with using a back quote (<TT><FONT FACE="Courier">`</FONT></TT>).
However, the double colon is the preferred, future way of addressing
variables within modules.
<P>
Explicit addressing of module variables is always done with a
complete reference. For example, suppose you have a module, <TT><FONT FACE="Courier">Investment</FONT></TT>,
which is the default package in use, and you want to address another
module, <TT><FONT FACE="Courier">Bonds</FONT></TT>, which is nested
within the <TT><FONT FACE="Courier">Investment</FONT></TT> module.
In this case, you cannot use <TT><FONT FACE="Courier">Bond::</FONT></TT>.
Instead, you would have to use <TT><FONT FACE="Courier">Investment::Bond::</FONT></TT>
to address variables and functions within the <TT><FONT FACE="Courier">Bond</FONT></TT>
module. Using <TT><FONT FACE="Courier">Bond::</FONT></TT> would
imply the use of a package <TT><FONT FACE="Courier">Bond</FONT></TT>
that is nested within the <TT><FONT FACE="Courier">main</FONT></TT>
module and not within the <TT><FONT FACE="Courier">Investment</FONT></TT>
module.
<P>
The symbol table for a module is actually stored in an associative
array of the module's names appended with two colons. The symbol
table for a module called <TT><FONT FACE="Courier">Bond</FONT></TT>
will be referred to as the associative array <TT><FONT FACE="Courier">%Bond::</FONT></TT>.
The name for the symbol table for the <TT><FONT FACE="Courier">main</FONT></TT>
module is <TT><FONT FACE="Courier">%main::</FONT></TT>, and can
even be shortened to <TT><FONT FACE="Courier">%::</FONT></TT>.
Similarly, all nested packages have their symbols stored in associative
arrays with double colons separating each nesting level. For example,
in the <TT><FONT FACE="Courier">Bond</FONT></TT> module that is
nested within the <TT><FONT FACE="Courier">Investment</FONT></TT>
module, the associative array for the symbols in the <TT><FONT FACE="Courier">Bond</FONT></TT>
module will be named <TT><FONT FACE="Courier">%Investment::Bond::</FONT></TT>.
<P>
A <TT><FONT FACE="Courier">typeglob</FONT></TT> is really a global
type for a symbol name. You can perform aliasing operations by
assigning to a <TT><FONT FACE="Courier">typeglob</FONT></TT>.
One or more entries in an associative array for symbols will be
used when an assignment via a <TT><FONT FACE="Courier">typeglob</FONT></TT>
is used. The actual value in each entry of the associative array
is what you are referring to when you use the <TT><FONT FACE="Courier">*<I>variableName</I></FONT></TT><I>
</I>notation. Thus, there are two ways of referring to variable
names in a package:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">*Investment::money = *Investment::bills;
<BR>
<BR>
$Investment::{'money'} = $Investment::{'bills'};</FONT></TT>
</BLOCKQUOTE>
<P>
In the first method, you are referring to the variables via a
<TT><FONT FACE="Courier">typeglob</FONT></TT> reference. The use
of the symbol table, <TT><FONT FACE="Courier">%Investment::</FONT></TT>,
is implied here, and Perl will optimize the lookup for symbols
<TT><FONT FACE="Courier">money</FONT></TT> and <TT><FONT FACE="Courier">bills</FONT></TT>.
This is the faster and preferred way of addressing a symbol. The
second method uses a lookup for the value of a variable addressed
by <TT><FONT FACE="Courier">'money'</FONT></TT> and <TT><FONT FACE="Courier">'bills'</FONT></TT>
in the associative array used for symbols, <TT><FONT FACE="Courier">%Investment::</FONT></TT>
explicitly. This lookup would be done dynamically and will not
be optimized by Perl. Therefore, the lookup will be forced to
check the associative array every time the statement is executed.
As a result, the second method is not efficient and should be
used only for demonstration of how the symbol table is implemented
internally.
<P>
Another example in this statement
<BLOCKQUOTE>
<TT><FONT FACE="Courier">*kamran = *husain;</FONT></TT>
</BLOCKQUOTE>
<P>
causes variables, subroutines, and file handles that are named
via the symbol <TT><FONT FACE="Courier">kamran</FONT></TT> to
also be addressed via the symbol <TT><FONT FACE="Courier">husain</FONT></TT>.
That is, all symbol entries in the current symbol table with the
key <TT><FONT FACE="Courier">kamran</FONT></TT> will now contain
references to those symbols addressed by the key <TT><FONT FACE="Courier">husain</FONT></TT>.
To prevent such a global assignment, you can use explicit references.
For example, the following statement will let you address the
contents of <TT><FONT FACE="Courier">$husain</FONT></TT> via the
variable <TT><FONT FACE="Courier">$kamran</FONT></TT>:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">*kamran = \$husain;</FONT></TT>
</BLOCKQUOTE>
<P>
However, any arrays such <TT><FONT FACE="Courier">@kamran</FONT></TT>
and <TT><FONT FACE="Courier">@husain</FONT></TT> will not be the
same. Only what the references specified explicitly will be changed.
To summarize, when you assign one <TT><FONT FACE="Courier">typeglob</FONT></TT>
to another, you affect all the entries in a symbol table regardless
of the type of variable being referred to. When you assign a reference
from one variable type to another, you are only affecting one
entry in the symbol table.
<P>
A Perl module file has the following format:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">package ModuleName;<BR>
...<BR>
#### <I>Insert module code </I>####<BR>
...<BR>
1;</FONT></TT>
</BLOCKQUOTE>
<P>
The filename has to be called <TT><FONT FACE="Courier">ModuleName.pm</FONT></TT>.
The name of a module must end in the string <TT><FONT FACE="Courier">.pm</FONT></TT>
by convention. The <TT><FONT FACE="Courier">package</FONT></TT>
statement is the first line of the file. The last line of the
file must contain the line with the <TT><FONT FACE="Courier">1;</FONT></TT>
statement. This in effect returns a <TT><FONT FACE="Courier">true</FONT></TT>
value to the application program using the module. Not using the
<TT><FONT FACE="Courier">1;</FONT></TT> statement will not let
the module be loaded correctly.
<P>
The <TT><FONT FACE="Courier">package</FONT></TT> statement tells
the Perl interpreter to start with a new namespace domain. Basically,
all your variables in a Perl script belong to a package called
<TT><FONT FACE="Courier">main</FONT></TT>. Every variable in the
<TT><FONT FACE="Courier">main</FONT></TT> package can be referred
to as <TT><FONT FACE="Courier">$main'variable</FONT></TT>.
<P>
Here's the syntax for such references:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">$packageName'variableName</FONT></TT>
</BLOCKQUOTE>
<P>
The single quote (<TT><FONT FACE="Courier">'</FONT></TT>) is synonymous
with the double colon (<TT><FONT FACE="Courier">::</FONT></TT>)
operator. I cover more uses of the <TT><FONT FACE="Courier">::</FONT></TT>
operator in the next chapter. For the time being, you must remember
that the following two statements are equivalent:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">$packageName'variableName;<BR>
$packageName::variableName;</FONT></TT>
</BLOCKQUOTE>
<P>
The double-colon syntax is considered standard in the Perl world.
Therefore, to preserve readability, I use the double-colon syntax
in the rest of this book unless it's absolutely necessary to make
exceptions to prove a point.
<P>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -