мой $self = сдвиг в Perl; объяснение

мне очень трудно понять пересечение Oo Perl и my $self = shift; документация по этим отдельным элементам великолепна, но ни один из них, который я нашел, не касается того, как они работают вместе.

Я использую Moose для создания модулей с атрибутами, и, конечно, полезно ссылаться на атрибут модуля в указанном модуле. Мне снова и снова говорили использовать my $self = shift; в рамках подпрограммы для присвоения атрибутов модуля этой переменной. Это имеет смысл и работает, но когда я также передаю аргументы подпрограмме, этот процесс явно принимает первый элемент @ARGV массив и присваивает его $self как хорошо.

может кто-нибудь предложить объяснение того, как я могу использовать shift для получения внутреннего доступа к атрибутам модуля, а также передавать аргументы в @ARGV массив?

3 ответов


во-первых, подпрограмма не передается @ARGV массив. Скорее все параметры, переданные подпрограмме, сглаживаются в один список, представленный @_ внутри подпрограммы. Массив @ARGV доступен на верхнем уровне вашего скрипта, содержащий аргументы командной строки, переданные вам скриптом.

теперь, в Perl, когда вы вызываете метод на объекте, Объект неявно передается в качестве параметра методу.

если вы игнорируете наследство,

 $obj->doCoolStuff($a, $b);

эквивалентно

 doCoolStuff($obj, $a, $b);

что означает содержание @_ в методе doCoolStuff будет: @_ = ($obj, $a, $b);

и shift встроенные функции, без каких-либо параметров, сдвигает элемент из переменной массива по умолчанию @_. В этом случае это было бы $obj.

поэтому, когда вы делаете $self = shift, вы фактически говорите $self = $obj.

я тоже надеюсь, что это объясняет, как пройти другие параметры метода через -> нотации. Продолжая пример, который я изложил выше, это было бы похоже:

sub doCoolStuff {
  # Remember @_ = ($obj, $a, $b)
  my $self = shift;
  my ($a, $b) = @_;

дополнительно, в то время как Moose является отличным объектным слоем для Perl, он не отнимает от требования, что вам нужно инициализировать $self в каждом методе. Всегда помни об этом. В то время как язык, такой как C++ и Java, инициализирует ссылку на объект this неявно, в Perl вам нужно сделать это явно для каждого метода, который вы пишете.


в верхнем уровне-кода shift() сокращенно shift(@ARGV). @ARGV содержит аргументы командной строки.

в суб, shift() сокращенно shift(@_). @_ содержит аргументы sub.

так my $self = shift; захватывает первый аргумент субмарины. При вызове метода, invocant (то, что осталось от ->) передается в качестве первого параметра. Другими словами,

$o->method(@a)

похож на

my $sub = $o->can('method');
$sub->($o, @a);

в этом примере my $self = shift; будет назначить $o to $self.


если вы называете:

$myinstance->myMethod("my_parameter");  

то же самое, что делал:

myMethod($myinstance, "my_parameter");  

но если вы:

myMethod("my_parameter");  

будет передан только "my_parameter".

тогда, если внутри myMethod всегда вы делаете:

 $self = shift @_;  

$self будет ссылкой на объект, когда mymethod id вызывается из контекста объекта
но будет "my_parameter" при вызове из другого метода внутри процедурным способом.
Знайте об этом;