Я створив модуль Foo ::Прототип із глобальними змінними $ A та $ B. Я хочу пакет Foo :: Bar, який використовує Foo :: Prototype як основу для імпорту глобальних змінних $ 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();
Редагувати:
Я хочу зробити підкласи написання Foo :: Prototype максимально компактними для інших людей. Замість того, щоб писати $ self -> {A} -> foo (), я б дозволив людям писати $ A-> foo ().
Відповіді:
5 за відповідь № 1Ну, є кілька питань:
Як вказує Брайан, Вашу проблему, мабуть, можна вирішити краще, не використовуючи глобальні змінні. Якщо ви опишете що ви намагаєтесь досягти, а не як, ми можемо дати кращі відповіді.
Якщо ви збираєтеся експортувати речі, вам знадобиться
sub import
або вам потрібно успадкувати відExporter
. Побачитиperldoc Exporter
.Незрозуміло, куди ви бажаєте зателефонувати
new
відбуватися.Як Грег вказує в коментарі нижче, змінні оголошені за допомогою
my
в обсязі пакета не можна експортувати. Тому я заявив$A
і$B
використовуючиour
.
Ось щось, що "працює", але вам доведеться трохи почитати та подумати, перш ніж вирішити, чи так ви хочете піти.
Час на вечір:
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
4 для відповіді № 2
Фокус у тому, що не потрібно експортувати змінні. Це дуже поганий спосіб програмування.
Можливо, є кращий спосіб досягти того, що ви хочете зробити. Ви просто повинні сказати нам, чому ви намагаєтесь це зробити.
4 для відповіді № 3
На основі вашого редагування, $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 :: Сінглтон.