При настройке кода Perl для запуска в качестве сценария или модуля, что является причиной для __PACKAGE__? - PullRequest
4 голосов
/ 01 августа 2009

В этом более раннем вопросе Stackoverflow и особенно Брайана Д. Фоя "Как скрипт становится модулем" Я читал о том, как настроить код так, чтобы его можно было запускать как либо скрипт, либо модуль, использующий эту технику:

package SomeModule;

__PACKAGE__->run(@ARGV) unless caller();

sub run {
    # Do stuff here if you are running the file as
    # a script rather than a module.
}

Какова цель __PACKAGE__ в этой настройке? Почему бы просто не сделать это?

run(@ARGV) unless caller();

1 Ответ

14 голосов
/ 01 августа 2009

Если вы говорите __PACKAGE__->run(@ARGV), тогда run может быть определено в классе, от которого вы наследуете, или позволяет классу наследовать от него. Если вы просто скажете run(@ARGV), вам не хватает информации о классе. Это имеет значение, только если вы занимаетесь программированием в стиле OO.

Поместите следующее в файл с именем Foo.pm, а затем скажите perl Foo.pm 1 2 3

package Foo;

use strict;
use warnings;

__PACKAGE__->main(@ARGV) unless caller;

sub main {
    my $class = shift;
    my $obj   = $class->new(@ARGV);
    print $obj->to_string, "\n";
}

sub new {
    my $class = shift;
    return bless [@_], $class;
}

sub to_string {
    my $self = shift;
    return "args: " . join ", ", map { "[$_]" } @$self;
}

1;

Теперь поместите следующее в Bar.pm и скажите perl Bar.pm a b c.

package Bar;

use strict;
use warnings;

use base 'Foo';

__PACKAGE__->main(@ARGV) unless caller;

sub to_string {
    my $self = shift;
    return "args: " . join ", ", map { "<$_>" } @$self;
}

1;

Теперь давайте посмотрим, что произойдет, если вы не используете __PACKAGE__ в этой среде. Сделайте первый раздел кода в Foo.pm похожим на это:

main(@ARGV) unless caller;

sub main {
    my $obj = Foo->new(@ARGV);
    print $obj->to_string, "\n";
}

Теперь запустите perl Foo.pm 1 2 3. Все должно выглядеть правильно. Теперь попробуйте запустить perl Bar.pm a b c. Мы все еще получаем результат, но это не результат, который мы ожидаем. Что произойдет, если мы удалим __PACKAGE__ из Bar.pm? Ну, мы получаем и ошибку: Undefined subroutine &Bar::main called at Bar.pm line 8. Это потому, что нет main функция в модуле, и мы не вызываем его вместе с классом, поэтому он больше не будет искать его в пакете Foo.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...