假如在sum2.pm中使用require导入了一个代码文件sum1.pm:数组
#!/usr/bin/env perl use strict; use warnings; use 5.010; require '/perlapp/sum1.pm'; sub sum { say "sum2: sum()"; } 1;
若是在sum1.pm中也有一个sum子程序:app
#!/usr/bin/env perl use strict; use warnings; use 5.010; sub sum { say "sum1: sum()"; } 1;
那么在运行sum2.pm的时候,将警告子程序从新定义。由于sum2.pm首先编译好本身的sum(),而后在运行期间require导入文件时,又再次定义sum(),将进行覆盖操做:ui
Subroutine sum redefined at /perlapp/sum1.pm.....
这样的名称冲突问题,经过声明包来解决。code
要定义一个包,只须要加上关键字package便可。作用域
package PKG_NAME [ VERSION_NUM ];
上面的语句用于声明包,能够带上包版本号,例如package pkg1 0.01;
。get
例如,在sum1.pm中:hash
#!/usr/bin/env perl use strict; use warnings; use 5.010; package Sum1; sub sum { say "pkg:Sum1,sum()"; } 1;
而后其它文件导入sum1.pm后,就可使用包名::属性
的方式访问sum1.pm中的属性,如子程序。io
#!/usr/bin/env perl use strict; use warnings; use 5.010; require '/perlapp/sum1.pm'; sub sum { say "file: sum2,sum()"; } sum(); # 访问本文件定义的sum子程序 Sum1::sum(); # 访问包Sum1::sum子程序,括号不能少 1;
除了子程序,包中的其它非词法做用域的属性也能被访问,包括:标量、数组、hash、文件句柄。例如:编译
$Sum1::name; @Sum1::arr;
每一个文件都至少定义在一个包内,若是没有显式给定package
指令,则这个包默认为main
包。因此,访问本程序文件内自身属性的时候可使用main:: + 属性
的方式。例如在sum2.pm中:require
#!/usr/bin/env perl use strict; use warnings; use 5.010; require '/perlapp/sum1.pm'; sub sum { say "file: sum2,sum()"; } sum(); # 访问本文件定义的sum子程序 main::sum(); # 等价于上一行直接访问sum() Sum1::sum(); # 访问包Sum1::sum子程序,括号不能少 1;
通常来讲,一个文件只会定义一个包。但容许一个文件定义经过包。
以下:
package Pkg1; ...code here belong to Pkg1... package Pkg2; ...code here belong to Pkg2...
定义多个包时,从包1到包2中间的全部属性都属于包1。
例如,在sum1.pm中:
#!/usr/bin/env perl use strict; use warnings; use 5.010; sub sum { # 位于默认的main包 say "pkg:main,sum()"; } package Sum1; # 第一个包 sub sum { # 位于Sum1包 say "pkg:Sum1,sum()"; } sum(); # 访问的是Sum1包的sum() main::sum(); # 访问的是main包的sum() package Sum2; # 第二个包 sub sum { # 位于Sum2包 say "pkg:Sum2,sum()"; } sum(); # 访问的是Sum2包的sum() Sum1::sum(); # 访问的是Sum1包的sum() main::sum(); # 访问的是main包的sum() 1;
有一些词语名称老是属于main包的: ARGV、ARGVOUT、ENV、INC、SIG、STDERR、STDIN 以及 STDOUT。有些带有特殊标点符号的名称(如$_,$2, $!
),它们也所有属于main。
另外,词法变量是不能使用包名访问的,由于使用包访问的属性,都是"全局"属性。因此,要在代码块中访问全局属性,能够加上包名:
package Sum1; out $var="1234"; sub mysub { my $var; ...$var...; # 访问的是my $var $Sum1::var; # 访问的是Sum1包中的$var }
若是将一个包声明放进代码块,则出了代码块的域后就消失:
package Sum1; { package main; sub sum { say "in main" } sum(); # 调用main中的sum } # 退出代码块,从新回到Sum1包 sub sum {code} # 属于Sum1包的sum子程序
从perl 5.12开始,支持包代码块:
use v5.12; package pkg1 { ... } package pkg2 { ... }
包代码块至关于词法范围:
package Navigation { my @homeport = (21.283, -157.842); # 属于包 sub get_me_home { my @homeport; # 声明词法变量 ... @homeport ... # 访问的是词法变量 ... @Navigation::homeport ... # 访问的是包变量 } ... @homeport ... # 访问的是包变量 }
它等价于:
{ package Navigation; my @homeport = (21.283, -157.842); # 属于包 sub get_me_home { my @homeport; # 声明词法变量 ... @homeport ... # 访问的是词法变量 ... @Navigation::homeport ... # 访问的是包变量 } ... @homeport ... # refers to the package variable }