В Perl объект - это просто ссылка на любой из основных типов данных Perl, который был благословлен в определенном классе. Когда вы используете функцию ref() для не благословленной ссылки, вам сообщается, на какой тип данных указывает ссылка. Однако, когда вы вызываете ref() для благословленной ссылки, вам возвращается имя пакета, в который эта ссылка была благословлена.
Я хочу знать фактический базовый тип благословленной ссылки. Как я могу это определить?
Scalar::Util::reftype()
является наиболее чистым решением. Модуль Scalar::Util
был добавлен в ядро Perl в версии 5.7, но доступен для старых версий (5.004 или более поздних) из CPAN.
Вы также можете выполнить зондирование с помощью UNIVERSAL::isa()
:
$x->isa('HASH') # if $x is known to be an object
UNIVERSAL::isa($x, 'HASH') # if $x might not be an object or reference
Очевидно, что вам также придется проверить наличие типов ARRAY
и SCALAR
. Модуль UNIVERSAL (который служит базовым классом для всех объектов) является частью ядра начиная с Perl 5.003.
Другой способ - простой, но немного грязный - заключается в структуризации ссылки. Предполагая, что класс не перегрузил стрингизацию, вы получите что-то похожее на Class=HASH(0x1234ABCD)
, что можно разобрать для извлечения базового типа данных:
my $type = ($object =~ /=(.+)\(0x[0-9a-f]+\)$/i);
Скорее всего, вам не следует этого делать. Базовый тип объекта - это деталь реализации, с которой не стоит связываться. Зачем вам это знать?
И моей первой мыслью по этому поводу было: "Объекты в Perl всегда являются хэш-рефренами, так что к чему этот хак?"
Но Scalar::Util::reftype - это ответ. Спасибо, что поместили вопрос здесь.
Вот фрагмент кода, доказывающий это (если это кому-нибудь пригодится).
$> perl -e 'use strict; use warnings "all"; my $x = [1]; bless ($x, "ABC::Def"); use Data::Dumper; print Dumper $x; print ref($x) . "\n"; use Scalar::Util "reftype"; print reftype($x) . "\n"'`.
Вывод:
$VAR1 = bless( [ 1 ], 'ABC::Def' ); ABC::Def ARRAY