Если вы включите строгую прагму, код даже не скомпилируется:
Global symbol "@_IncludePath" requires explicit package name at Packet.pm line 15.
Global symbol "@_IncludePath" requires explicit package name at Packet.pm line 29.
Global symbol "@_IncludePath" requires explicit package name at Packet.pm line 30.
Global symbol "@_IncludePath" requires explicit package name at Packet.pm line 40.
Не используйте @
без кавычек в ваших ключах, потому что это запутает анализатор. Я рекомендую полностью удалить их, чтобы не запутать читателей вашего кода.
Кажется, вы хотите извлечь все значения атрибутов из аргументов в конструктор, поэтому продолжайте снимать скалярные значения с помощью shift
, а затем все, что осталось, должно быть путем включения. *
Я предполагаю, что компоненты пути включения будут простыми скалярами, а не ссылками; если последнее так, то вы захотите сделать глубокие копии для безопасности.
sub new {
my $class = shift;
my $Packet = {
_PacketName => shift,
_Platform => shift,
_Version => shift,
_IncludePath => [ @_ ],
};
bless $Packet, $class;
}
Обратите внимание, что нет необходимости хранить благословенный объект во временной переменной, а затем немедленно возвращать его из-за семантики подпрограмм Perl :
Если return
не найдено и если последний оператор является выражением, возвращается его значение.
Приведенные ниже методы также будут использовать эту функцию.
Учитывая конструктор выше, GetIncludePath
становится
sub GetIncludePath {
my( $Packet ) = @_;
my @path = @{ $Packet->{_IncludePath} };
wantarray ? @path : \@path;
}
Здесь происходит несколько вещей. Во-первых, обратите внимание, что мы стараемся возвращать копию пути включения, а не прямую ссылку на внутренний массив. Таким образом, пользователь может изменить значение, возвращаемое из GetIncludePath
, не беспокоясь о том, чтобы испортить состояние пакета.
Оператор wantarray
позволяет подчиненному определить контекст своего вызова и ответить соответствующим образом. В контексте списка GetIncludePath
вернет список значений в массиве. В противном случае он возвращает ссылку на копию массива. Таким образом, клиентский код может вызывать его как в
foreach my $path (@{ $packet->GetIncludePath }) { ... }
или
foreach my $path ($packet->GetIncludePath) { ... }
SetIncludePath
тогда
sub SetIncludePath {
my ( $Packet, @IncludePath ) = @_;
$Packet->{_IncludePath} = \@IncludePath;
}
Обратите внимание, что вы могли бы использовать подобный код в конструкторе, а не удалять по одному параметру за раз с shift
.
Вы можете использовать класс, определенный выше, как в
#! /usr/bin/perl
use strict;
use warnings;
use Packet;
sub print_packet {
my($p) = @_;
print $p->GetPacketName, "\n",
map(" - [$_]\n", $p->GetIncludePath),
"\n";
}
my $p = Packet->new("MyName", "platform", "v1.0", qw/ foo bar baz /);
print_packet $p;
my @includeobjects = (
"./input/myMockPacketName",
"./input/myPacket/my3/*.txt",
"./input/myPacket/in.html",
);
$p->SetIncludePath(@includeobjects);
print_packet $p;
print "In scalar context:\n";
foreach my $path (@{ $p->GetIncludePath }) {
print $path, "\n";
}
Выход:
MyName
- [foo]
- [bar]
- [baz]
MyName
- [./input/myMockPacketName]
- [./input/myPacket/my3/*.txt]
- [./input/myPacket/in.html]
In scalar context:
./input/myMockPacketName
./input/myPacket/my3/*.txt
./input/myPacket/in.html