我使用全局变量$ A和$ B创建了一个模块Foo :: Prototype。我想要使用Foo :: Prototype作为基础来导入全局变量$ A和$ B的包Foo :: Bar。我无法想象如何做到这一点。
我知道使用全局变量通常不是一个好习惯,但在这种情况下我想使用它们。
代码如下所示:
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();
修改
我想让其他人尽可能地为Foo :: Prototype编写子类。我不想写$ self-> {A} - > foo(),而是让人们写$ A-> foo()。
答案 0 :(得分:5)
嗯,有一些问题:
作为brian points out,您可以在不使用全局变量的情况下更好地解决问题。如果您描述的是 ,而不是 ,我们可能会提供更好的答案。
如果您要导出内容,则需要sub import
或者需要继承Exporter
。请参阅perldoc Exporter
。
目前尚不清楚您希望调用new
的位置。
正如Greg在下面的评论中指出的那样,无法导出在包范围内使用my
声明的变量。因此,我使用$A
声明$B
和our
。
这是“有效”的东西,但在决定这是否是您想要的方式之前,您将不得不做一些阅读和思考。
<强> 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 :(得分:4)
诀窍是不必导出变量。这是一种非常糟糕的编程方式。
也许有更好的方法来完成你想做的事情。你只需要告诉我们你为什么要这样做。
答案 2 :(得分: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。