2010-04-12 47 views
16

我需要定義一些模塊並在同一個文件中使用它們。不,我不能改變這個要求。如何調用我在同一個文件中定義的Perl包?

我想這樣做如下:

{ 
    package FooObj; 

    sub new { ... } 

    sub add_data { ... } 
} 

{ 
    package BarObj; 

    use FooObj; 

    sub new { 
     ... 
     # BarObj "has a" FooObj 
     my $self = (myFoo => FooObj->new()); 
     ... 
    } 

    sub some_method { ... } 
} 

my $bar = BarObj->new(); 

但是,這導致在消息中:

在@公司無法找到FooObj.pm ...
BEGIN失敗...

我該如何得到這個工作?

+3

提示是在這裏的錯誤:「無法找到FooObj.pm」。 .pm總是意味着一個文件。 – 2010-04-12 16:50:42

回答

23

刪除use。認真。

use告訴perl從另一個文件讀取代碼,由於代碼位於同一個文件中,因此您不需要執行此操作。

+0

如何在不使用'use'的情況下導入'Exporter'導出的任何東西? – ceving 2015-11-10 15:31:57

+0

@ceving直接調用'import'。例如,在這個問題的代碼中(如果它使用'Exporter'),'FooObj-> import(@params)'。 – 2015-11-11 08:22:15

+0

不,我有一個不同的問題:http://stackoverflow.com/q/33634898/402322 – ceving 2015-11-11 08:25:04

14

除非我試圖創建一個沒有人應該知道的私有包,否則我會爲每個文件放置一個包。解決了這個問題。但是,讓我們把它們放在同一個文件中。

use加載文件並調用該包中的import方法。它的參數看起來像一個模塊名稱,這真的只是顯而易見的。它正在尋找文件。如果該文件不在那裏,那就是barf。

你可以做到這一點,在那裏BarObj假定FooObj已經存在:

{ 
    package FooObj; 
    sub new  { bless { _count => 0 }, $_[0] } 
    sub add_data { $_[0]->{_count}++ } 
} 

{ 
    package BarObj; 
    use Data::Dumper; 

    sub new { 
     bless { myFoo => FooObj->new }, $_[0]; 
     } 

    sub foo   { $_[0]->{myFoo} } 
    sub some_method { print Dumper($_[0]) } 
} 

my $bar = BarObj->new; 
$bar->some_method; 

如果你需要一個包交互(而這一切,它是:不是一個模塊或對象),你只要在你想使用它之前需要定義它。如果您需要進口的東西,你可以撥打import直接:

FooObj->import(...); 

假設有一個從FooObj要導入(而不是繼承!),你叫import直接沒有加載的東西;

{ 
    package FooObj; 
    use Data::Dumper; 
    sub new  { bless { _count => 0 }, $_[0] } 
    sub add_data { $_[0]->{_count}++ } 

    use Exporter qw(import); 
    our @EXPORT = qw(dumper); 
    sub dumper { print Dumper($_[0]) } 
} 

{ 
    package BarObj; 
    FooObj->import; 

    sub new { 
     bless { myFoo => FooObj->new }, $_[0]; 
     } 

    sub foo   { $_[0]->{myFoo} } 

    # dumper mixin, not inherited. 
    sub some_method { dumper($_[0]) } 
} 

my $bar = BarObj->new; 
$bar->some_method; 
10

按照慣例,我們把一個軟件包放在一個文件中,並命名爲相同的東西,但這只是爲了方便。您可以將多個軟件包放在一個文件中。由於它們已經加載,所以不需要使用use

您也不需要爲包創建特殊的範圍,因爲package關鍵字處理該包。使用大括號有助於確定變量的範圍。所以你不需要那些大括號,但他們是個好主意。

use使用包命名約定來查找要加載的相應文件。模塊內的package關鍵字定義了命名空間。導入函數處理包加載(通常從Exporter繼承)。

#!/usr/bin/perl 

use strict; 
use warnings; 

package FooObj; 

sub new 
{ 
     my $this = shift; 
     my $class = ref($this) || $this; 
     my $self = {}; 
     bless $self, $class; 
     $self->initialize(); 
     return $self; 
} 

sub initialize { } 
sub add_data { } 

package BarObj; 

#use FooObj; <-- not needed. 

sub new 
{ 
     my $this = shift; 
     my $class = ref($this) || $this; 
     my $self = { myFoo => FooObj->new() }; 
     bless $self, $class; 
     $self->initialize(); 
     return $self; 
} 
sub initialize { } 
sub some_method { } 
sub myFoo  { return $_[0]->{myFoo} } 

package main; 
use Test::More; 
my $bar = BarObj->new(); 
isa_ok($bar,  'BarObj', "bar is a BarObj"); 
isa_ok($bar->myFoo, 'FooObj', "bar->myFoo is a FooObj"); 
done_testing(); 

__DATA__ 

ok 1 - bar is a BarObj isa BarObj 
ok 2 - bar->myFoo is a FooObj isa FooObj 
1..2 
+2

+1對於有趣的信息,但我仍然喜歡使用大括號,因爲我認爲它增加了視覺清晰度。 – 2010-04-12 17:24:19

+0

羅伯特,我明白你的觀點。爲了視覺上的清晰,我經常使用(命名的)裸括號 - 通常在我決定將給定部分重構爲自己的例程之前,或者驅動程序腳本需要將更多功能移回模塊之前。 我不會經常把多個軟件包放在一個文件中,所以沒有真正考慮需要支撐還是不支撐。 – spazm 2010-04-12 17:30:32

+6

這不僅是清晰度,而且是一個範圍問題。包不創建一個範圍,所以你的那個my()變量的文件範圍沒有大括號,否則會限制它。 – 2010-04-12 21:22:34

相關問題