標籤:預設 env efi 包括 定義 詞法 需要 app $2
名稱衝突問題
假如在sum2.pm中使用require匯入了一個代碼檔案sum1.pm:
#!/usr/bin/env perluse strict;use warnings;use 5.010;require '/perlapp/sum1.pm';sub sum { say "sum2: sum()";}1;
如果在sum1.pm中也有一個sum子程式:
#!/usr/bin/env perluse strict;use warnings;use 5.010;sub sum { say "sum1: sum()";}1;
那麼在運行sum2.pm的時候,將警告子程式重新定義。因為sum2.pm首先編譯好自己的sum(),然後在運行期間require匯入檔案時,又再次定義sum(),將進行覆蓋操作:
Subroutine sum redefined at /perlapp/sum1.pm.....
這樣的名稱衝突問題,通過聲明包來解決。
定義包和訪問包屬性
要定義一個包,只需要加上關鍵字package即可。
package PKG_NAME [ VERSION_NUM ];
上面的語句用於聲明包,可以帶上包版本號碼,例如package pkg1 0.01;
。
例如,在sum1.pm中:
#!/usr/bin/env perluse strict;use warnings;use 5.010;package Sum1;sub sum { say "pkg:Sum1,sum()";}1;
然後其它檔案匯入sum1.pm後,就可以使用包名::屬性
的方式訪問sum1.pm中的屬性,如子程式。
#!/usr/bin/env perluse 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中:
#!/usr/bin/env perluse 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 perluse 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
}
Perl包相關