Perl: модули сталкиваются, когда оба импортируют один и тот же модуль - PullRequest
2 голосов
/ 20 января 2012

Допустим, у меня есть два модуля, A и Bee, каждый из которых использует третий мод, Shared.

A:

package A;
BEGIN {
    use Shared;
    use Bee;
}

sub new {
    my ($class) = @_;
    my $self = {};
    bless $self, $class;
    $self->B(Bee->new);
    $self;
}

sub B {
    my($self, $B) = @_;
    $self->{b} = $B if defined $B;
    $self->{b};
}

sub test {
    shared_sub();
}

Bee:

package Bee;

BEGIN {
    use Shared;
}

sub new {
    my ($class) = @_;
    my $self = {};
    bless $self, $class;
    $self;
}

sub test {
    shared_sub();
}

1;

Общий (обратите внимание, что он не объявляет имя пакета):

#!/usr/bin/perl
use strict;
use warnings;
BEGIN {
    require Exporter;

    our @ISA = qw(Exporter);
    our @EXPORT_OK = qw(shared_sub);
}

sub shared_sub {
    print "This is the shared sub in package '" . __PACKAGE__ . "'\n";
}

1;

Из сценария, который вызывает A:

use A;
my $A = A->new;
$A->test;       # This is the shared sub in package 'A'
$A->B->test;    # Undefined subroutine &Bee::shared_sub called at Bee.pm line 19.

Из сценария, который вызывает только Bee:

use Bee;
my $B = Bee->new;
$B->test;   # This is the shared sub in package 'Bee'

По отдельности и A, и Bee могут безошибочно вызывать метод test (), но когда я вкладываю Bee в A, именно тогда Bee вдруг не может найти метод Shared;не импортируется ли он в пространство имен любого вызывающего его модуля?

Очевидный ответ - дать Shared собственное имя пакета, а затем обновить все модули, которые его используют, но мне интересно, есть ли способ избежать этого с помощью более простого решения.

1 Ответ

4 голосов
/ 20 января 2012

Используйте require (и, следовательно, use) только с модулями (файлы с package). Используйте do в противном случае. Если вы этого не сделаете, вы получите эту проблему.

require исполнял файл только один раз, но вам нужно запускать его один раз для каждого модуля, который его использует.

Модули выполняются только один раз, но вы ожидаете, что код будет выполняться каждый раз, когда вы выполняете use Shared;

Пчела больше не может найти общий метод

Shared никогда не имеет методов. Такое пространство имен не создается.

Очевидный ответ - дать Shared собственное имя пакета и затем обновить все модули, которые его используют,

Вам не нужно обновлять никакие файлы, кроме Shared.pm.

...