perl 允许你将代码划分成一个或多个可重用的模块
1.使用关键字package 来定义模块
2.使用use和require 来加载预定义模块
3.使用"::" 记号来存取包的特定变量和子例程
包的基本知识:
关键词 package 标示着一个新的名字空间的开始,在它之后声明的所有的全局标识符
(包括变量名,子例程,文件句柄,打印格式和目录句柄)都将属于这个包(package) 例如:
Vsftp:/root/perl/15# cat BankAccount.pm
package BankAccount;
$total = 99;
sub deposit {
my $amount = shift;
$total += $amount;
print "You now have $total dollars \n";
};
sub withdraw {
my $amount = shift;
$total -=$amount;
$total=0 if $total <0;
print "You now have $total dollars\n";
};
1;
Vsftp:/root/perl/15# cat a1.pl
unshift(@INC,"/root/perl/15");
use BankAccount;
my $total =10;
print "\$total is $total\n";
print "111111111111111111\n";
print $BankAccount::total."\n";
print &BankAccount::deposit(12);
print &BankAccount::withdraw(20);
Vsftp:/root/perl/15# perl a1.pl
$total is 10
111111111111111111
99
You now have 111 dollars
1You now have 91 dollars
Perl 切换包:
Vsftp:/root/perl/15# cat a2.pl
unshift(@INC,"/root/perl/15");
use BankAccount;
use ATM;
my $total =10;
print "\$total is $total\n";
print "111111111111111111\n";
package BankAccount;
print $BankAccount::total."\n";
print "22222222222222222222\n";
package ATM;
print $ATM::total."\n";
包与变量:
在第三章"Typeglob与符号表"中,我曾提到所有的全局名字都位于一个符号表中。
这有点像一个善意的谎言,实际上每个包都有它自己的符号表,它们之间互补相同
包与文件:
同一个包的声明可以放在多个文件中,或者多个包可以在一个文件中进行声明。
加载路径:
Perl 首先在内建数组@INC 指定的路径中查找使用use或require给定的文件
Vsftp:/root/perl/15# perl -e 'print "@INC\n"'
/usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .
包的初始化和销毁:
有时候你需要在任何代码执行前来做一些初始化工作,Perl的功能更为强大:
它允许你仍处在编译节点就有机会执行代码
Vsftp:/root/perl/15# cat a4.pl
sub BEGIN {
print "Washington was here \n";
};
for**r;
Vsftp:/root/perl/15# perl a4.pl
Washington was here
Bareword found where operator expected at a4.pl line 4, near "**r"
(Missing operator before r?)
Operator or semicolon missing before *r at a4.pl line 4.
Ambiguous use of * resolved as operator * at a4.pl line 4.
syntax error at a4.pl line 4, near "for**"
Execution of a4.pl aborted due to compilation errors.
Vsftp:/root/perl/15# cat a5.pl
print "11111111\n";
for**r;
Vsftp:/root/perl/15# perl a5.pl
Bareword found where operator expected at a5.pl line 2, near "**r"
(Missing operator before r?)
Operator or semicolon missing before *r at a5.pl line 2.
Ambiguous use of * resolved as operator * at a5.pl line 2.
syntax error at a5.pl line 2, near "for**"
Execution of a5.pl aborted due to compilation errors.
虽然带有语法错误得到程序一般根本就不会执行,然而位于错误之前的BEGIN 子例程还是得到了执行
私有性:
Perl 中的符号是可以任意存取的,信息隐藏并不是强制的。
强制私有性:
你可以在文件范围内使用my操作符来获得绝对安全的私有变量,
因为我们和包没有任何联系,所以无法从别的域中进行存取(在这里就是指文件范围内)
符号的导入:
有时候为了省去输入的麻烦,你可能需要有选择的将一些符号导入到自己的名字空间中。
符号的导出和导入:
Vsftp:/root/perl/15# cat BankAccount.pm
package BankAccount;
use Exporter;
@ISA=qw(Exporter); ##继承Exporter
@EXPORT_OK=('withdraw','deposit'); ##导出方法
sub withdraw {
my $a=shift;
my $b =shift;
return $a + $b;
};
sub deposit {
my $a=shift;
my $b=shift;
return $a * $b;
};
1;
Vsftp:/root/perl/15# cat a8.pl
unshift(@INC,"/root/perl/15");
use BankAccount qw/withdraw deposit/;
print &withdraw(3,4);
print "\n";
print &deposit(3,4);
print "\n";
Vsftp:/root/perl/15# perl a8.pl
7
12
如果模块使用@EXPORT 来代替@EXPORT_OK的话,那么用户将输出缺省的所有符号,而不管在输入列表中是否提及这些符号
我建议,作为一个模块编写人员,还是使用更礼貌的@EXPORT_OK好一些
use和Exporter 是如何工作的:
包的嵌套:
当你使用use File时,你会记得Perl 将会查找名为File.pm 的文件。
当你使用use Math::Poisson 时,Perl 将查找名位Math/Poisson.pm (Math为目录,Poisson.pm为文件)
自动加载: