Должен ли я устанавливать наследование во время компиляции, а не во время выполнения, и если да, то почему? - PullRequest
6 голосов
/ 13 февраля 2010

AFAIK наследование в Perl обычно настраивается так:

package Mule;
our @ISA = ("Horse", "Donkey");

Есть ли примеры, где use base (или use parent) лучше?

Ответы [ 3 ]

5 голосов
/ 13 февраля 2010
use base qw(Horse Donkey);

Это примерно эквивалентно:

BEGIN {
    require Horse;
    require Donkey;
    push @ISA, qw(Horse Donkey);
}

Это более удобно, если вам нужно загрузить код модулей, а также наследовать от них.Кстати, есть проблемы с множественным наследованием, но это другой вопрос:)

Редактировать: Время компиляции v. Преимущества времени выполнения:

  • Выиметь безопасность проверки времени компиляции с помощью use base , что означает, что ваш скрипт даже не запустится, если ваш базовый модуль отсутствует в файловой системе.
  • Если вы хотитерешите использовать данный модуль во время выполнения, тогда вы можете протестировать и добавить модуль к своим родителям:

    if (eval {require X}) {push @ISA, 'X';}

3 голосов
/ 15 февраля 2010

Установление наследования во время компиляции позволяет избежать особенно сложного для отладки цикла зависимостей, как показано ниже.

# Child.pm
package Child;

our @ISA = qw(Mother);

use Foo;

# Mother.pm
package Mother;

sub wibble { 42 }

# Foo.pm
package Foo;

use Child;
Child->wibble;

Если вы «используете Child» перед «use Foo», Foo попытается вызвать Child->wibble до того, как его наследование установится на Mother. Если вместо этого Child будет use parent qw(Mother), его наследование будет установлено до того, как он попытается загрузить что-либо еще.

Я был подобным циклом зависимостей в частном корпоративном коде, который, как правило, немного более переплетен, чем открытый код. Это отстойно для отладки, поэтому я бы рекомендовал всегда устанавливать наследование во время компиляции.

1 голос
/ 14 февраля 2010

Относительно времени компиляции и времени выполнения:

В Perl модули (пакеты / пространства имен) обычно находятся в отдельных файлах. То есть Some::Module будет найдено в Some / Module.pm. В этой настройке разница compile-vs-run-time не будет иметь большого значения. Время выполнения модуля, загружаемого вами через use(), будет до того, как продолжится время компиляции вызывающего кода. Наблюдатель:

Файл Some/Module.pm:

package Some::Module;
BEGIN{ print "Some::Module - compile time\n" }
print "Some::Module - run time\n";
1;

Файл test.pl:

BEGIN{ print "Just started compiling the program.\n" }
use Some::Module;
BEGIN{ print "main - compile time\n" }
print "main - run time\n";

Вывод будет:

Just started compiling the program.
Some::Module - compile time
Some::Module - run time
main - compile time
main - run time

Следовательно, our @ISA = qw(Base); будет выполняться до того, как компиляция вашей основной программы продолжится после загрузки модуля.

Однако правильно, что присвоение @ISA не гарантирует, что базовый класс был загружен. Вот почему у нас есть use base и use parent прагмы. Если вам конкретно не нужны какие-либо функции use base (поля) и не требуется более длительная обратная совместимость, которую она обеспечивает для use parent, я предлагаю вам использовать более легкую use parent.

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