Что означает __PACKAGE __-> {foo}?
Я перерабатываю модуль perl в устаревшем коде, и это функция из модуля:
sub get_user {
my $user = __PACKAGE__->{user};
if (!defined $user) {
# more code
__PACKAGE__->{user} = $user;
}
return $user;
}
Этот модуль компилируется под use strict
. И нет никаких переменных пакета.
Что означает __PACKAGE__->{user}
?
Ответы
Ответ 1
__PACKAGE__
- имя текущего пакета; ваш код использует его как символическую хеш-ссылку. Поэтому, если ваш пакет foo, он устанавливает $foo::foo{'user'}
. Это странная вещь; Я подозреваю, что это может быть ошибка.
Поскольку это символическая ссылка, ее нельзя допускать строго. Однако, похоже, по крайней мере, когда текущий пакет имеет несколько частей (например, Foo:: Bar, а не только Foo).
Однако я бы не стал зависеть от этой ошибки.
Ответ 2
use strict;
use warnings;
use 5.012;
{
package X::Y;
our $user = 10;
say $user;
say __PACKAGE__;
}
--output:--
10
X::Y
Название пакета может быть "X:: Y", но таблица символов для пакета называется "X:: Y::" (обратите внимание на хвостовые двоеточия). Таблица символов - это хеш perl, а ключи в хешах% X:: Y:: - глобальные имена, используемые в пакете X:: Y. Соответствующие значения являются типами символов для каждого имени:
use strict;
use warnings;
use 5.012;
{
package X::Y;
our $user = 10;
say $user;
say __PACKAGE__;
say $X::Y::{user}; #Hash name is %X::Y::
}
--output:--
10
X::Y
*X::Y::user
Но выражение в op:
__PACKAGE__->{user}
эквивалентно:
'X::Y'->{user}
Я не вижу, как эта строка удастся получить что-либо из хэша, чье имя "X:: Y::" (заканчивается двумя двоеточиями). И на самом деле, я получаю эту ошибку:
use strict;
use warnings;
use 5.012;
{
package X::Y;
our $user = 10;
say $user;
say __PACKAGE__;
say $X::Y::{user};
say __PACKAGE__->{user};
}
--output:--
10
X::Y
*X::Y::user
Use of uninitialized value in say at 2.pl line 13.
Если код действительно создает хэш с именем% X:: Y где-то, тогда код будет работать без ошибок:
use strict;
use warnings;
use 5.012;
%X::Y = (); #This hash has nothing to do with the hash named
#%X::Y::, which is the symbol table for the
#X::Y package.
$X::Y{user} = 'hello';
{
package X::Y;
sub get_user {
say __PACKAGE__->{user};
}
get_user;
}
--output:--
hello
Как упоминалось в комментарии, хэш X X:: Y не имеет ничего общего с пакетом X:: Y. Фактически, строка:
%X::Y = ();
явно объявляет переменную Y в пакете X. Пакет X и пакет X:: Y представляют собой два разных пакета.
И нет никаких переменных пакета
Подменю - это переменная пакета:
use strict;
use warnings;
use 5.012;
{
package X::Y;
sub get_user {say 'hello';}
say $X::Y::{get_user};
}
--output:--
*X::Y::get_user
Тот факт, что typeglob для имени 'get_user' существует, означает, что в коде используется хотя бы одна глобальная переменная с именем get_user.
Ответ 3
__PACKAGE__
является хешем. Этот синтаксис обращается к ключевому значению.