Подклассы Perl наследуют импортированные модули и прагмы? - PullRequest
10 голосов
/ 11 августа 2010

Допустим, у вас есть родительский класс Perl в одном файле:

#!/usr/bin/perl
package Foo;
use strict;
use warnings;

use Data::Dumper;

sub new{
    my $class = shift;
    my %self = ();
    return bless %self, $class;
}
1;

и подкласс в другом файле:

#!/usr/bin/perl
package Bar;
use base "Foo";
1;

Будет ли подкласс наследовать операторы использования от родителя? Я знаю, что новый метод будет наследоваться.

В основном я пытаюсь уменьшить количество стандартного кода в моем коде, и я не могу найти четкий ответ на этот вопрос.

Ответы [ 5 ]

7 голосов
/ 11 августа 2010

Вы спросили в комментарии о Test :: Most и о том, как это уменьшает шаблон. Посмотрите на его import метод. Он загружает модули в свое пространство имен, добавляет эти символы в @EXPORT, затем повторно вызывает другие import через goto, чтобы, наконец, получить их в вызывающее пространство имен. У Кертиса есть какая-то серьезная черная магия, хотя мне интересно, почему он просто не использовал что-то вроде import_to_level . Может быть, есть некоторые побочные эффекты, о которых я не думаю.


Я довольно много говорю о подобных вещах в Избегайте случайного создания методов из экспорта модулей в Effective Perler . Это в другом контексте, но это одни и те же проблемы.

Вот другой пример.

Если какой-то другой модуль загружает модуль, у вас есть к нему доступ. Это не хорошо, чтобы зависеть от этого, хотя. Вот три отдельных файла:

Top.pm

use 5.010;

package Top;
use File::Spec;

sub announce { say "Hello from top!" }
1;

Bottom.pm

package Bottom;
use parent qw(Top);

sub catfiles { File::Spec->catfile( @_ ) }

1;

test.pl

use 5.010;

use Bottom;

say Bottom->catfiles( qw(foo bar baz) );

say File::Spec->catfile( qw( one two three ) );

Я загружаю только File :: Spec в Top.pm . Однако после загрузки я могу использовать его в любом месте моей Perl-программы. Вывод показывает, что мне удалось «использовать» модуль в других файлах, хотя я загружал его только в один:

Bottom/foo/bar/baz
one/two/three

Чтобы это работало, часть кода, которая загружает модуль, должна быть загружена до того, как любая другая часть кода попытается использовать этот модуль. Как я уже сказал, плохо полагаться на это: вещи ломаются, если изменяется последовательность загрузки или исчезает модуль загрузки.

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

4 голосов
/ 11 августа 2010

Ах, хороший вопрос!

Will the subclass inherit the use statements from the parent? 

Ну, это зависит от того, что вы подразумеваете под наследованием.Я не буду делать никаких предположений до конца, но ответ будет возможно .Видите ли, Perl смешивает идеи Classes, а Namespaces - package - это термин, который может описать любой из них.Теперь проблема заключается в утверждении use, все, что он делает, это принудительно включает пакет и вызывает цель import() sub.Это означает, что он по сути имеет неограниченный контроль над вашим пакетом - и, таким образом, ваш класс.

Теперь, соедините это со всеми методами в perl, которые будут не более чем subs, которые принимают $self в качестве первого аргумента.по соглашению, и вы остались с Perl5.Это имеет огромный плюс для тех, кто знает, как его использовать.В то время как строгая лексическая прагма, как насчет Moose?

package BigMooseUser;
use Moose;

package BabyMooseUser;
our @ISA = 'BigMooseUser';

package Foo;
my $b = BabyMooseUser->new;
print $b->meta->name;

Теперь, откуда BabyMooseUser получил конструктор (новый)?Откуда он взял мета класс?Все это предоставляется из единственного use Moose; в родительском классе (пространстве имен).Итак,

Will the subclass inherit the use statements from the parent?

Хорошо, здесь, в нашем примере, если эффекты оператора use заключаются в добавлении методов, чем, конечно,.

Эта тема является своего родаглубоко, и это зависит от того, говорите ли вы о прагмах, или о более неясных объектных структурах, или о процедурных модулях.Если вы хотите, чтобы пространство имен родителей не влияло на ваше собственное в парадигме ОО, см. namespace::autoclean.

4 голосов
/ 11 августа 2010

Для сокращения шаблонов у меня есть пара стратегий: большинство моих классов - Moose , которые занимаются настройкой ОО, а также дают мне строгие предупреждения и предупреждения. Если я хочу, чтобы функции были доступны во многих пакетах, я создам модуль MyProject::Util для конкретного проекта, который использует Sub-Exporter , чтобы предоставить мне свои собственные функции и собственный интерфейс. Это делает его более последовательным, и если я по какой-либо причине решу изменить Dumper (например) позже, мне не придется менять много кода. Это также позволит вам группировать экспорт. Класс обычно выглядит примерно так:

package Foo;
use Moose;
use MyProject::Util qw( :parsing :logging );

use namespace::autoclean;

# class implementation goes here

1;

Если есть и другие вещи, которые вы считаете стандартными и хотите упростить включение, это, конечно, зависит от того, что это за вещи.

2 голосов
/ 11 августа 2010

Прагматичный ответ на вашу проблему: либо используйте, либо посмотрите, как Modern::Perl делает это для обеспечения строгости и предупреждений.

1 голос
/ 11 августа 2010

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

# examine-symbol-tables.pl
use Bar;

%parent_names = map{$_ => 1} keys %Foo::;
%child_names = map{$_ => 1} keys %Bar::;

delete $parent_names{$_} && ($common_names{$_} = delete $child_names{$_}) foreach keys %child_names;

print "Common names in symbol tables:\n";
print "@{[keys %common_names]}\n\n";

print "Unique names in Bar symbol table:\n";
print "@{[keys %child_names]}\n\n";

print "Unique names in Foo symbol table:\n";
print "@{[keys %parent_names]}\n\n";

$ perl inherit.pl
Common names in symbol tables:
BEGIN

Unique names in Bar symbol table:
ISA isa import

Unique names in Foo symbol table:
<b>Dumper</b> new VERSION
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...