模塊
之前我們介紹了如何使用函數(shù)、類和數(shù)據(jù)結構來組織代碼裹虫,接下來要介紹的是另一個用來組織代碼和擴展代碼的機制--模塊。一個模塊就是一個文件包,可以用use或require 來加載壹士。模塊必須要是有效的Perl代碼。模塊必須以一個真值結尾偿警,這樣Perl解析器才能知道模塊是否被成功的加載和編譯躏救。
當你加載一個模塊時,Perl以雙冒號分割模塊名轉換成文件路徑螟蒸。例如盒使,use StrangeMonkey::Persistence;
Perl就會在@INC中查找每一個叫StrangeMonkey的目錄,并且在每一個叫StrangeMonkey的目錄中查找一個名字為Persistence.pm的文件(實際上就是找StrangeMonkey/Persistence.pm文件)七嫌;use StrangeMonkey::UI::Mobile;
Perl就會在@INC中查找StrangeMonkey/UI/Mobile.pm文件少办。
使用模塊來組織代碼
Perl并不強制要求你使用模塊、包或名字空間诵原,你可以將所有代碼都放入單個.pl文件或多個.pl文件英妓,可以選擇最舒服的方式靈活地來開發(fā)、管理皮假、部署你的代碼鞋拟,當然這其中的風險和收益就取決于你自己的經(jīng)驗水平了。
盡管如此惹资,我們建議你在代碼量超過幾百行后就使用模塊來組織代碼:
- 模塊會強制在系統(tǒng)的不同實體之間進行邏輯分離贺纲。
- 無論你是否使用OO,模塊都能提供API邊界褪测。
- 模塊提倡以一種自然的方式來組織源代碼猴誊。
- Perl生態(tài)系統(tǒng)中有很多工具專門用于創(chuàng)建潦刃、組織、部署和分發(fā)模塊懈叹。
- 模塊提供了代碼重用的機制乖杠。
即使你不使用面向對象,模塊也能幫助對代碼進行更好地封裝澄成。
****使用和導入****
當你使用use加載一個模塊時胧洒,Perl就會從磁盤中加載文件,然后調(diào)用它的import()方法(如果有參數(shù)的話還會傳遞參數(shù))墨状。按照慣例卫漫,一個模塊的import()方法,會將一系列名字肾砂、導出函數(shù)和其他符號標記導入到自己的名字空間列赎。當然這只是一個約定,模塊也有可能拒絕提供import()函數(shù)或者import()函數(shù)執(zhí)行的是其他行為镐确,如編譯指示strict 包吝,作用是在調(diào)用者的詞法范圍內(nèi)改變行為而不是導出符號:
use strict;
# ... calls strict->import()
use CGI ':standard';
# ... calls CGI->import( ':standard' )
use feature qw( say switch );
# ... calls feature->import( qw( say switch ) )
關鍵字no會調(diào)用模塊的unimport()方法(有參數(shù)還會傳遞參數(shù))。最常見的就是搭配import() 來改變程序的行為:
use strict;
# no symbolic references or barewords
# variable declaration required
{
no strict 'refs';
# symbolic references allowed
# strict 'subs' and 'vars' still in effect
}
use和no都會在編譯的時候就生效:
use Module::Name qw( list of arguments );
#等同于
BEGIN
{
require 'Module/Name.pm';
Module::Name->import( qw( list of arguments ) );
}
類似的:
no Module::Name qw( list of arguments );
#等同于:
BEGIN
{
require 'Module/Name.pm';
Module::Name->unimport(qw( list of arguments ));
}
都是可選的源葫!
如果模塊沒有import()或unimport()函數(shù)Perl也不會報錯诗越。
你也可以直接調(diào)用import()和unimport()函數(shù),盡管在BEGIN塊之外它們沒有什么作用息堂;編譯結束后 import()和unimport()就沒什么用了掺喻。
use和require都是區(qū)分大小寫的,所以use strict和use Strict是不一樣的:一個是加載strict.pm储矩,一個是加載Strict.pm。但你的操作系統(tǒng)或文件系統(tǒng)可能不會區(qū)分大小寫褂乍,對于一個不區(qū)分大小寫的文件系統(tǒng)持隧,use strict在找不到strict.pm文件時Perl會去加載Strict.pm,但是當你嘗試調(diào)用Strict->import()時卻什么都不會發(fā)生逃片,所以謹慎對待大小寫總是好的屡拨。
****導出****
一個模塊可以通過導出自己的全局包符號,這樣別的包就可以直接或間接調(diào)用import()來使用這些符號褥实。
核心模塊Exporter就是導出符號的標準途徑呀狼。Exporter依賴2個全局變量@EXPORT_OK和@EXPORT,它們包含了一系列要導出的符號损离。
模塊StrangeMonkey::Utilitie提供了幾個單獨的函數(shù):
package StrangeMonkey::Utilities;
use Exporter 'import';
our @EXPORT_OK = qw( round translate screech );
...
任何其他的代碼都可以使用這個模塊和導入這些函數(shù)(round哥艇,translate,screech)僻澎。你也可以導出變量:
push @EXPORT_OK, qw( $spider $saki $squirrel );
也可以使用@EXPORT代替@EXPORT_OK來實現(xiàn)類似的功能:
our @EXPORT = qw( monkey_dance monkey_sleep );
這樣在任何地方使用use StrangeMonkey::Utilities都會導入這些函數(shù)貌踏。要明白的是如果指定的要導入的符號十饥,那就不會導入其他的符號;你只會得到你想要的祖乳。若要加載一個模塊逗堵,但是不想導入任何符號,那就使用明確的空列表:
# make the module available, but import() nothing
use StrangeMonkey::Utilities ();
不使用導入列表眷昆,也總是可以通過使用完全限定名來調(diào)用函數(shù)的(這你應該知道的吧):
StrangeMonkey::Utilities::screech();
簡化導出
CPAN模塊Sub::Exporter提供了更友好的接口來導出函數(shù)蜒秤。
CPAN模塊Moose::Exporter用于基于Moose的系統(tǒng)。