模块

Perl允许你将代码划分成一个或多个可重用的模块。

1.使用关键词package 来定义模块:

2.使用use和require来加载预定义模块

3.使用":"记号来存取包的特定变量和子例程


包的资本知识:

关键词package 标志这一个新的名字空间的开始,在它之后声明的所有的全局标识符(

包括变量名,子例程,文件句柄,打印格式和目录句柄)都将属于这个package.

[root@node01 4]# cat BankAccount.pm 
package BankAccount;
$total = 99;
sub deposit {
    my $amount=shift;
    $total +=$amount;
    print "You now have $total dollars
";
}

sub withdraw {
    my $amount=shift;
    $total -=$amount;
    $total=0 if $total<0;
    print "You now have $total dollars
";
};
1;


用户定义的全局标识符$total,deposit和withdraw属于包BankAccount.

包的作用域一直延伸到最内存的封闭代码块的结束

[root@node01 4]# cat a3.pl 
unshift(@INC,"/root/perl/4");  
use BankAccount;
my $total=88;
print "1---$total=$total
";

print $BankAccount::total;
print "
";
[root@node01 4]# perl a3.pl 
1---$total=88
99

注意包里的变量必须是全局变量:



包和变量:

在第三章"Typeglob与符号表"中,我曾提到所有的全局名字都位于一个符号表中。

这个有点像一个善意的谎言。

实际上每个包都有它自己的符号表,它们之间互不相同。

那些诸如$|,$_,@ARGV和%ENV之类的内奸变量总是属于包main的。

这些事Perl中唯一真正的全局变量:

符号引用:

加载途径:
[root@node01 4]# perl -e 'print "@INC
";'
/usr/local/perl/lib/site_perl/5.22.1/x86_64-linux /usr/local/perl/lib/site_perl/5.22.1 /usr/local/perl/lib/5.22.1/x86_64-linux /usr/local/perl/lib/5.22.1 .


包的初始化与销毁:

[root@node01 4]# cat a3.pl 
unshift(@INC,"/root/perl/4");  
use BankAccount;
my $total=88;
print "1---$total=$total
";

print $BankAccount::total;
print "
";
foo**;
[root@node01 4]# perl a3.pl 
syntax error at a3.pl line 8, near "**;"
Execution of a3.pl aborted due to compilation errors.

带有语法错误的程序一般根本就不会执行

私有性:

Perl 中的符号是可以任意存取的,信息隐藏并不是强制性的。

联机文档中就形象的描述到:

强制私有性:

你可以在文件范围内使用my操作符来获得绝对安全的私有变量。

符号的导入:

有时为了省去输入的麻烦,你可能需要有选择的将一些符号导入到自己的名字空间中。

例如,你想以sqrt来代替math::sqrt 或者以deposit代替BankAccount::deposit.

use 语句可以让你指定一组可选的用来导入的函数名:

[root@node01 6]# cat a1.pl 
use BankAccount('withdraw','deposit');

print withdraw();  #现在你无须使用全能限定就能调用它了


就模块来说,它必须已经准备好向任何use它的程序输出这些名字(也只有这些名字).

[root@node01 6]# cat BankAccount.pm 
package BankAccount;
use Exporter;
@ISA=('Exporter'); ##继承Exporter

@EXPORT_OK=('withdraw','deposit');

sub deposit {return "111111111111
";};

sub withdraw {return "222222222222
"};
1;

use和Exporter 是如何工作的:


包的嵌套:

既然所有包在作用域上都是全局性的,因此并不支持包嵌套。

然而你却可以有两个包,一个称做A,另一个称做A::B,

这给出了一种包嵌套的错觉。

当你使用use File时,你会记得Perl将会查找名为File.pm的文件。

当你使用
use Math::Poisson时,Perl将查找名为Math/Poisson.pm(Math为目录,Poisson.pm为文件)


自动加载:


比如说,如果你调用了一个名为Test::func()的函数,而func()并没有在Test模块中定义,

Perl则会自动寻找一个称做Test::AUTOLOAD()的子例程。






随便调用一个函数,如果这个函数不存在就调用autoload函数

如果autoload函数你也没实现,那么就返回函数不存在的错误

名为$AUTOLOAD的变量将被设置为刚才所调用函数的全名("Test::func");
[root@node01 6]# cat Mt.pm 
package Mt;
our $AUTOLOAD;
sub AUTOLOAD {
  print "$AUTOLOAD=$AUTOLOAD
";
   my $program=$AUTOLOAD;
  $program=~s/^.*:://g;
  print "$program=$program
";
  system("$program @_");
    };
  1;
[root@node01 6]# cat a2.pl 
use Mt;
Mt::ls('-lt');
[root@node01 6]# perl a2.pl 
$AUTOLOAD=Mt::ls
$program=ls
total 16
-rw-r--r-- 1 root root 195 Apr 22 11:18 Mt.pm
-rw-r--r-- 1 root root  23 Apr 22 11:17 a2.pl
-rw-r--r-- 1 root root 193 Apr 22 06:49 BankAccount.pm
-rw-r--r-- 1 root root  59 Apr 22 06:47 a1.pl



[root@node01 6]# cat a3.pl 
foreach $name (keys %main::){
 print "$name,
";
};
[root@node01 6]# perl a3.pl 
_<perl.c,
_<universal.c,
/,
0,

原文地址:https://www.cnblogs.com/hzcya1995/p/13349760.html