2009-06-24 109 views
0

我用全局變量$ A和$ B創建了一個模塊Foo :: Prototype。我想要使​​用Foo :: Prototype作爲基礎的Foo :: Bar包導入全局變量$ A和$ B。我無法想象如何做到這一點。如何從基礎模塊導入全局變量?

我明白,使用全局變量並不是一個好的做法,但在這種情況下,我想使用它們。

的代碼看起來是這樣的:

package Foo:Prototype; 
my ($A, $B); 
our @EXPORT = qw($A $B); 

sub new { 
    [...] 
    $A = 1; 
    $B = 2; 
} 

1; 

package Foo:Bar; 
use base Foo:Prototype qw($A $B); 

sub test { 
    print $A, "\n"; 
    print $B, "\n"; 
} 

1; 


# test.pl 
Foo:Bar->new(); 
Foo:Bar->test(); 

編輯:

我要讓富::原型寫子類儘可能緊湊其他人。而不必編寫$ self - > {A} - > foo(),我寧願讓人們編寫$ A-> foo()。

回答

5

嗯,有幾個問題:

  1. 由於brian points out,你的問題或許可以得到解決,而無需使用全局變量更好。如果你描述的是你試圖實現的是什麼而不是如何,我們可能可以提供更好的答案。

  2. 如果您要導出東西,您需要一個sub import或您需要從Exporter繼承。見perldoc Exporter

  3. 您不清楚您要撥打new的電話發生在哪裏。

  4. 由於Greg在下面的註釋中指出,在軟件包範圍聲明爲my的變量不能導出。因此,我使用our宣佈$A$B

這是「有效」的東西,但在決定這是否是你想要的方式之前,你將不得不做一些閱讀和思考。

T.pm:

package T; 
use strict; 
use warnings; 

use base 'Exporter'; 

our ($A, $B); 
our @EXPORT = qw($A $B); 

sub new { 
    $A = 1; 
    $B = 2; 
} 

"EOF T.pm" 

U.pm:

package U; 

use strict; 
use warnings; 

use base 'T'; 
use T; 

sub test { 
    my $self = shift; 
    print "$_\n" for $A, $B; 
} 

"EOF U.pm" 

t.pl:

#!/usr/perl/bin 
use strict; 
use warnings; 

use U; 

U->new; 
U->test; 

C:\Temp> t.pl 
1 
2 
+1

不錯的答案。你含蓄地說過,但我會強調出口商不會出口詞彙。 – 2009-06-24 22:20:15

+0

@gbacon謝謝。 – 2009-06-24 22:29:42

4

訣竅是沒有導出變量LES。這是一個非常糟糕的編程方式。

也許有更好的方法來完成任何你想做的事情。你只需告訴我們你爲什麼要這麼做。

4

根據您的編輯,$A$B將用於調用方法。

因此,我假設他們是存儲爲基類的類數據的單例對象。

如果將它們作爲變量公開,它們可以很容易地更改,並且可能會發生各種問題。

爲什麼不使用存取器?

package Foo::Proto; 

my $A; 
my $B; 

sub A { 
    return $A; 
} 

sub B { 
    return $B; 
} 

package Foo::Child; 
our @ISA= qw(Foo::Prototype); 

sub test { 
    my $self = shift; 

    $self->A->blah(); 

    # Or if I am doing many things with A, and want to type less: 
    my $A = $self->A; 
    $A->blah(); 
} 

package Foo::Kid; 
our @ISA= qw(Foo::Prototype); 

# If you will never change $A in the prototype, you could do this: 
my $A = __PACKAGE__->A; 

sub test { 
    $A->blah(); 
} 

但是,這一切似乎是一個很大的麻煩。

要在我的代碼中解決這個問題,我會使用Moose,然後創建一個角色來引入A和B相關的方法。

my $m = Foo::Mooseling->new(); 
$m->test_A(); 
$m->test_B(); 


BEGIN { # This is going to be $A, I needed something to call $A->foo on. 
    package Thing1; 
    sub new { bless {}, __PACKAGE__; } 
    sub foo { print __PACKAGE__."::foo()\n"; } 
    sub blah { print __PACKAGE__."::blah()\n"; } 
} 
BEGIN { # This is going to be B. It is not interesting either. 
    package Thing2; 
    sub new { bless {}, __PACKAGE__; } 
    sub bar { print __PACKAGE__."::bar()\n"; } 
    sub bluh { print __PACKAGE__."::bluh()\n"; } 
} 

# This is the interesting part:  
BEGIN { # This ROLE will provide A and B methods to any objects that include it. 
    package Foo::ProtoMoose; 
    use Moose::Role; 

    has 'A' => (
     is => 'ro', 
     isa => 'Thing1', 
     handles => [qw(foo blah)], # Delegate calls to foo and blah for consuming object to this A. 
     default => sub { Thing1->new(); }, # Create a Thing1 to be A. 
    ); 

    has 'B' => (
     is => 'ro', 
     isa => 'Thing2', 
     handles => [qw(bar bluh)],  
     default => sub { Thing2->new(); }, 
    ); 
} 

BEGIN { # This method consumes the ProtoMoose Role. 
    package Foo::Mooseling; 
    use Moose; 

    with 'Foo::ProtoMoose'; 

    sub test_A { 
     my $class = shift; 

     $class->foo; 
     $class->blah; 
    } 

    sub test_B { 
     my $class = shift; 

     $class->bar; 
     $class->bluh; 
    } 

} 

如果你想Thing1和Thing2是單身人士,請使用MooseX::Singleton