мой $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" при вызове из другого метода внутри процедурным способом.
Знайте об этом;