假如在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 }