Perl Packages, Modules and Object Classes


Packages

Packages are independent of files. Many packages can fit in a single file, or a single package can span several files. Usually there is one file per package, in which case if the name of the file is the same name as the package and has an extension of .pm it is a perl module. A package thus provides a (hopefully) unique namespace.

There is no such thing as a global variable in Perl (except for certain magic variables). Code and variables always refer to the current package. The initial currenbt package is package main, but you can switch at any time by using the package declaration. The current package determines which symbol table to use (for names that aren't package qualified). Most name lookups happen at compile time, but run time lookups happen when symbolic references are derefernced, and also when new bits of code are parsed with eval. In particular, eval operations know which package they were invoked in, andpropagate that package inward as the current package. You can always switch to a different package within the eval string (which counts as a block, as does a fileloaded with do, require, or use).

The scope of a package declaration is from the declaration itself through the of of the innermost enclosing block (or until another package declaration at the same level, which hides the earlier one). All subsequent identifiers (except those declared with my, or those qualified with a different pacvkage name) will be placed in the symbol table belonging to the package.

Typically, you would put a package declaration as the first declaration in a file to be included by require or use. But again, that's by convention. A pacakge declaration can be put anywhere a statement can be put. It can be put even at the end of a block, in which case it would have no effect. One can switch into a package in more than one place; it merely influences which symbol table is used fo the rest of the block. This is how a given package can span more than one file.

Identifiers in other packages can be refered to by prefixing (i.e. qualifying) the identifier with the package name and a double colon:
   $Package::$Variable
If the package name is null, the main package is assumed. That is $::sail is equivalent to $main::sail. Old syntax used a quote mark: $main'sail and $'sail.

Packages may be nested inside other packages: $OUTER::INNER::var. This implies nothing about the order of name lookups. There are no fallback symbol tables. All undeclared symbols are either local to the current package, or must be fully qualified from the outer package name down. Every package declaration must declare a complete package name. No package name ever assumes any kind of implied prefix.

Only identifires (names starting with a letter or underscore) are stored in the current package's symbol table. All other symbols are kept in package main, including all the punctuation only variables like $! and $_. The special identifiers STDIN, STDOUT, STDERR, RGV, ARGVOUT, ENV, INC, and SIG are also in package main. If you have a package called m, s, y, or tr, then you cannot use the qualified form of an identifier as a filehandle because it will be interpreted instead as a pattern match, a substitution, or a translation. Using uppercase package names avoids this problem.

Assignment of a string to %SIG assumes the signal handler specified is in the main package, if the name is unqualified. Qualify the signal handler name to have a signal handler in a package, or don't use a string at all: assign a typeglob or a function reference instead:

$SIG{QUIT} = "quit_catcher";    # implies "main::quit_catcher"
$SIG{QUIT} = *quit_catcher;     # forces current package's sub
$SIG{QUIT} = \&quit_catcher";   # forces current package's sub
$SIG{QUIT} = sub { print "Caught SIGQUIT\n" }; # anonymous sub

Symbol Tables

The symbol table for a package is stored in a hash whose name is the same as the package name with two colons appended. The main symbol table's name is thus: %main::, or %:: for short. Similarly the symbol table for the nested package mentioned above is: %OUTER::INNER::. The main symbol table contains all other top level symbol tables, including itself, so %OUTER::INNER:: is also %main::OUTER:INNER::. Since package main is a top level package, it conatins a reference to itself, thus %main:: is the same as main::main::, and also is %main::main::main::, and so on, ad infinitum. It is important to check for this special case if you write code to traverse all symbol tables.

The keys in a symbol table hash are the identifiers of the symbols in the symbol table. The values in a symbol table hash are the corresponding typeglob values. So when you use the *name typeglob notation, you are really accessing a value in the hash that holds the current package's symbol table. the follwoing thus have the same effet, but the first may be faster because it does the table lookup at compile time:

local *somesym = *main::variable;
local *somesym = $main::{"variable"};

Since a package is a hash, look up all the keys of the package, and hence all the variables of the package. Try this:

foreach $symname (sort keys %main::) {
   local *sym = $main::{symname};
   print "\$$symname is defined\n" if defined $sym;
   print "\@$symname is defined\n" if defined @sym;
   print "\%$symname is defined\n" if defined %sym;
}

Assignment to a typeglob performs an aliasing operation; e.g. *dick = *richard; causes everything accesible via the identifier richard to also be available via the symbol dick. If you only want to alias a particular variable or subroutine, assign a reference instead: *dick = \$richard; which makes $richard and $dick the same variable, but leaves @richard and @dick as separate arrays. This only works on package variables though, which means declared with local, but not with my.


Modules

The module is the unit of reusability in Perl. A module is used with the use command, which is a directive that controls the importation of unctions and variables from a module.


Object Classes

Object classes build on the package concept. The typical class is implemented with a module. Object oriented programming in Perl is accomplished with references that happen to refer to things that know which class they are associated with.