模块

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为文件)


自动加载:

posted @ 2016-12-01 17:12  czcb  阅读(153)  评论(0编辑  收藏  举报