2010-08-19 99 views
4

我有一個相當複雜的數據結構,我在Perl中實現。這已經被分成大約20個班。基本上,任何時候你想使用這些類中的一個,你需要使用所有這些類。如何製作一個爲用戶導入多個模塊的模塊?

現在,如果有人想用這種數據結構,他們需要做的是這樣的:

use Component::Root; 
use Component::Foo; 
use Component::Bar; 
use Component::Baz; 
use Component::Flib; 
use Component::Zen; 
use Component::Zen::Foo; 
use Component::Zen::Bar; 
use Component::Zen::Baz; 
... # 15 more of these... 
use Component::Last; 

能夠操縱它的所有部件。我怎麼能寫一個模塊,這是否給用戶,所以他們所要做的就是

use Component; 

讓所有其它模塊的進口?

在這種特殊情況下,模塊都是類,並且沒有導出。

+0

重複:[?我怎樣才能組織許多Perl模塊(http://stackoverflow.com/questions/2788670/how-should-i-organize-many-perl-modules) – Zaid 2010-08-20 14:33:04

回答

6

如果這些都只是類(即不出口任何函數或變量,當你use他們),那麼所有真正重要的是,他們都被載入。

只需創建Component.pm

package Component; 

our $VERSION = '1.00'; 

use Component::Root; 
use Component::Foo; 
use Component::Bar; 
use Component::Baz; 
use Component::Flib; 
use Component::Zen; 
use Component::Zen::Foo; 
use Component::Zen::Bar; 
use Component::Zen::Baz; 
... # 15 more of these... 
use Component::Last; 

1; # Package return value 

你不需要Exporter或類似的東西。

但是,將這些use語句放入根節點的類中或創建數據結構的模塊中可能更有意義,而不是具有use語句的模塊。也就是說,人們會想說:這取決於如何你的數據結構通常是創建

use Component::Root; 
my $root = Component::Root->new(...); 

use Component qw(build_structure); 
my $root = build_structure(...); 

。它可能有點令人困惑的人寫:

use Component; 
my $root = Component::Root->new(...); 

但它確實取決於你的API看起來像。如果有很多人可能打電話給new,那麼use Component可能是要走的路。

+0

你的第二個想法是完全正確的:用戶將在一個或另一個位置創建大多數Component :: *對象的新實例,至少在初始階段或者他們想要手動完成。 – 2010-08-19 19:23:31

+0

你的第二個想法對於創建好物體很重要。通過在對象的根節點中包含所有必需的支持模塊,該對象是獨立的。這是封裝的重要組成部分。 如果我必須調用兩個模塊,一個模塊帶有新的模塊和其他模塊以引入所有引用,那麼該對象不是獨立的。 – HerbN 2010-08-19 21:33:24

+0

'1)'我不敢相信這是一個真正的問題。我很想知道這僅僅是爲了創造點。 - 當然你只是把它們全部包裝在一起。 - '2)'關於第二個,它取決於有多少類可能需要加載,如果它只是一個,則將它們加載到基類中。如果需要使用該功能的應用程序不止一個,則將它們全部打包在一個模塊中,並從其他每個軟件包中調用該模塊。 – vol7ron 2010-08-20 01:51:01

0

Moose::Exporter似乎這樣做,但所有其他模塊也必須使用它。

Component

Moose::Exporter->setup_import_methods(
    also => [qw/Component::Root Component::..*/], 
); 
1
  • 你可以使用所有這些軟件包Exporter S中export_to_level方法。

    MyPackage->export_to_level($where_to_export, $package, @what_to_export); 
    
  • 您也可以導出所有導入的符號。

    use PackageA qw<Huey Dewey Louie>; 
    ... 
    our @ISA = qw<Exporter>; #inherit Exporter 
    our @EXPORT = qw<Huey Dewey Louie>; 
    
  • 但是,如果你不想出口任何符號,只是要加載的模塊,然後只包括那些use上述聲明,並在這個過程中任何包就能實例化它們作爲類,說如果他們都是面向對象的模塊。

    假設它們已成功加載,它們將存在於%INC和符號表中。

+0

這是一個好想法,如果你需要導出一些東西,但在這種情況下,沒有東西可以導出。 – cjm 2010-08-19 22:48:06

0

如果模塊不出口任何東西,沒有一個導入方法(同樣要求軍事審判的答案),你只需要加載的模塊,而進口:

package Component; 

our $VERSION = '1.00'; 

require Component::Root; 
require Component::Foo; 
require Component::Bar; 
require Component::Baz; 
require Component::Flib; 
require Component::Zen; 
require Component::Zen::Foo; 
require Component::Zen::Bar; 
require Component::Zen::Baz; 
... # 15 more of these... 
require Component::Last; 

1; # Package return value 

模塊的用戶將只更多信息:

require Component; 

然而,如果一些模塊做出口,你將不得不調用它們import方法。所以,你有你的Component模塊中添加import方法,將稱他們爲:

sub import 
{ 
    Component::Root->import; 
    Component::Foo->import; 
    ... 
} 

等模塊的用戶將不得不use它:

use Component; 

注意,你可能必須使用一些其他的竅門如果導入的模塊必須在導入器的上下文中插入符號。例如,請參閱POE's import如何執行此操作。

0

Modern::Perl模塊吹捧本身與「啓用所有的現代的Perl的特徵用一個命令」,其中該命令是

use Modern::Perl; 

和那些特徵是

現在,這隻有啓用嚴格和警告編譯指示,以及Perl 5.10中提供的所有功能。它還可以啓用C3方法解析順序;請參閱perldoc mro的解釋。

這是一個很大的一行代碼,其中根據perlmod documentation是完全等同於

BEGIN { require Module; import Module; } 

考慮現代:: Perl的implementation

package Modern::Perl; 

our $VERSION = '1.03'; 

use 5.010_000; 

use strict; 
use warnings; 

use mro (); 
use feature(); 

sub import { 
    warnings->import(); 
    strict->import(); 
    feature->import(':5.10'); 
    mro::set_mro(scalar caller(), 'c3'); 
} 

1; # End of Modern::Perl 

要適應這個你從您的頂級模塊use您想要加載的所有其他模塊,並從MyTopLevelModule::import中調用其導入(如果有)。

注意,你不一定需要

use 5.010_000; 

複製到MyTopLevelModule.pm,但是這將是一個好主意!根據use documentation

在特有use VERSION形式,VERSION可以是正的小數如5.006,這將在相比$],或形式v5.6.1的V串,這將與$^V(又名$PERL_VERSION)進行比較。如果VERSION大於當前Perl解釋器的版本,則會引發異常; Perl不會嘗試解析文件的其餘部分。與require比較,它可以在運行時進行類似的檢查。