Как это вызовет подпрограмму в модуле Perl?
Недавно я увидел некоторый код Perl, который меня смутил. Я достал все лишние детали, чтобы посмотреть, как он работает, но я до сих пор не понимаю, почему он работает.
В принципе, я создал этот фиктивный "модуль" (TTT.pm):
use strict;
use warnings;
package TTT;
sub new {
my $class = shift;
return bless {'Test' => 'Test'}, $class;
}
sub acquire {
my $tt = new TTT();
return $tt;
}
1;
Затем я создал этот script для использования модуля (ttt.pl):
#!/usr/bin/perl
use strict;
use warnings;
use TTT;
our $VERSION = 1;
my $tt = acquire TTT;
print $tt->{Test};
Линия, которая меня смущает, которая, как я думал, не сработает, такова:
my $tt = acquire TTT;
Я думал, что это не сработает, так как "приобретать" юг никогда не экспортировался. Но это действительно работает.
Я был смущен "TTT" после вызова для приобретения, поэтому я удалил его, оставив строку следующим образом:
my $tt = acquire;
И он жаловался на одно слово, как я думал. Я добавил parens, вот так:
my $tt = acquire();
И он жаловался, что не было main::acquire
, как я думал, это будет.
Я использую подпрограммы, доступные для объекта, или подпрограммы, экспортируемые, но я никогда не видел, чтобы подпрограмма вызывалась с именем пакета в конце. Я даже не знаю, как искать это в Google.
Итак, мой вопрос: как добавить имя пакета после вызова подпрограммы? Я никогда не видел ничего подобного раньше, и это, вероятно, не очень хорошая практика, но может кто-то объяснить, что делает Perl?
Спасибо!
Ответы
Ответ 1
Вы используете синтаксис косвенных объектов, который позволяет Perl (но в современном коде не рекомендуется). В принципе, если имя не предопределено, оно может быть помещено перед объектом (или именем класса), разделенным пробелом.
Таким образом, строка acquire TTT
означает TTT->acquire
. Если у вас на самом деле была подпрограмма с именем acquire
в области видимости, она вместо этого была бы интерпретирована как aquire(TTT)
, что может привести к двусмысленности (отсюда почему она не поощряется).
Вы также должны обновить строку new TTT();
в методе, чтобы прочитать TTT->new;
Ответ 2
Это косвенный синтаксис объекта для вызовов методов, который позволяет помещать имя метода перед именем объекта.
Как видно из документации, ее лучше избегать, поскольку она громоздка и может быть непредсказуемой, например, если есть импортированная или определенная подпрограмма с именем acquire
- но она была более распространенной, чем сегодня, и поэтому вы найдете его довольно часто в старом коде и документах.