Perl: экспорт символов из модуля, который имеет> 1 пакет - PullRequest
7 голосов
/ 10 ноября 2009

модуль foo / bar.pm

package foo::bar;
stuff
stuff
package foo::wizzy;
require Exporter;
our @ISA=qw(Exporter);
our @EXPORT=qw(x);
use constant
{
  x=>1
};

потребитель, который делает

use Foo::bar;

не получает foo::wizzy::x экспорт

Я знаю, что могу сделать из него два отдельных модуля, но все же я должен быть в состоянии сделать эту работу, не так ли?

Ответы [ 4 ]

7 голосов
/ 10 ноября 2009

Вы можете сделать это, используя метод export_to_level Экспортера, чтобы "основной пакет" реэкспортировал символы "другого" пакета, например так:

sub import {
   my $self = shift;
   $self->export_to_level(1, @_);
   Some::Other::Module->export_to_level(1);
}

хотя, если Some::Other::Module делает что-то более сложное, чем "экспортировать все", вам, вероятно, понадобится более сложная обработка для @_.

Мне действительно нужно спросить , почему , хотя & ndash; я не могу представить себе использование этого, которое совместимо со словами "хороший код":)

7 голосов
/ 10 ноября 2009

Когда вы звоните use foo::bar, на самом деле происходит следующее:

BEGIN {
    require foo::bar;
    foo::bar->import;
}

(см. perldoc -f use )

Так что import никогда не вызывается на foo::wizzy. Если вы также хотите импортировать эти символы, вы можете позвонить BEGIN { foo::wizzy->import } самостоятельно (после use foo::bar). Или, как вы сказали, просто разбейте эти два пакета на отдельные файлы, которые были бы намного более удобочитаемыми для человека.

(Между прочим, не рекомендуется использовать имена пакетов в нижнем регистре, так как они, как правило, зарезервированы для perl pragmata.)

3 голосов
/ 10 ноября 2009

В конце модуля поставить:

BEGIN { $INC{'foo/wizzy.pm'} = 1 }

Тогда код может просто сказать:

use foo::bar;
use foo::wizzy;

чтобы получить экспорт foo :: wizzy.

2 голосов
/ 10 ноября 2009

Прежде всего, я считаю полезным использовать заключающие в скобки скобки для управления областью при объединении нескольких пакетов в один файл. Кроме того, включение пакета в блок BEGIN делает его более похожим на use, который использовался для его загрузки, но это в основном, если я собираю пакет в основной скрипт.

use Foo совпадает с BEGIN { require Foo; Foo->import }.

Итак, у вас есть два варианта:

  • вызов BEGIN{ Foo::Whizzy->import; } в вашем основном скрипте.
  • делает Foo::Bar::import триггер Foo::Whizzy::import на вызывающем модуле.

В Foo / Bar.pm:

{ package Foo::Bar;
  use Exporter qw( export_to_level );

  # Special custom import.  Not needed if you call Foo::Whizzy->import
  sub import {
    shift;
    export_to_level('Foo::Whizzy', 1, @_ );
  }

  # stuff
  # stuff
}

{ package Foo::Whizzy;
  require Exporter;

  our @ISA=qw(Exporter);
  our @EXPORT=qw(x);
  use constant  { x=>1 };

}

1; # return true

В вашем основном коде:

use Foo::Bar;

# If you don't do a custom import for Foo::Bar, add this line:
BEGIN { Foo::Whizzy->import };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...