[英]How do I use an array as an object attribute in Perl?
我需要一些關於Perl中數組的幫助
這是我的構造函數。
BuildPacket.pm
sub new {
my $class = shift;
my $Packet = {
_PacketName => shift,
_Platform => shift,
_Version => shift,
_IncludePath => [@_],
};
bless $Packet, $class;
return $Packet;
}
sub SetPacketName {
my ( $Packet, $PacketName ) = @_;
$Packet->{_PacketName} = $PacketName if defined($PacketName);
return $Packet->{_PacketName};
}
sub SetIncludePath {
my ( $Packet, @IncludePath ) = @_;
$Packet->{_IncludePath} = \@IncludePath;
}
sub GetPacketName {
my( $Packet ) = @_;
return $Packet->{_PacketName};
}
sub GetIncludePath {
my( $Packet ) = @_;
@{ $Packet->{_IncludePath} };
}
(代碼已經根據'gbacon'的建議進行了修改,謝謝)
我以動態的方式將相對路徑推入'includeobjects'數組。 正在從xml文件中讀取include路徑並將其推送到此數組中。
# PacketInput.pm
if($element eq 'Include')
{
while( my( $key, $value ) = each( %attrs ))
{
if($key eq 'Path')
push(@includeobjects, $value);
}
}
所以,includeobject將是這樣的:
@includeobjects = (
"./input/myMockPacketName",
"./input/myPacket/my3/*.txt",
"./input/myPacket/in.html",
);
我正在使用此行來設置包含路徑
$newPacket->SetIncludePath(@includeobjects);
同樣在PacketInput.pm
,我有
sub CreateStringPath
{
my $packet = shift;
print "printing packet in CreateStringPath".$packet."\n";
my $append = "";
my @arr = @{$packet->GetIncludePath()};
foreach my $inc (@arr)
{
$append = $append + $inc;
print "print append :".$append."\n";
}
}
我有很多數據包,所以我循環遍歷每個數據包
# PacketCreation.pl
my @packets = PacketInput::GetPackets();
foreach my $packet (PacketInput::GetPackets())
{
print "printing packet in loop packet".$packet."\n";
PacketInput::CreateStringPath($packet);
$packet->CreateTar($platform, $input);
$packet->GetValidateOutputFile($platform);
}
get和set方法適用於PacketName。 但由於IncludePath是一個數組,我無法讓它工作,我的意思是相對路徑沒有打印。
如果啟用strict pragma,則代碼甚至無法編譯:
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.
不要在密鑰中使用@
unquoted,因為它會使解析器混淆。 我建議完全刪除它們,以免混淆人類讀者的代碼。
您似乎想要將所有屬性值從參數拉到構造函數,因此繼續使用shift
剝離標量值,然后剩下的所有內容必須是包含路徑。
我假設include路徑的組件將是簡單的標量而不是引用; 如果是后者,那么你會想要為安全做出深刻的副本。
sub new {
my $class = shift;
my $Packet = {
_PacketName => shift,
_Platform => shift,
_Version => shift,
_IncludePath => [ @_ ],
};
bless $Packet, $class;
}
請注意,由於Perl subs的語義,不需要將blessed對象存儲在臨時變量中,然后立即返回它:
如果未找到
return
值,並且最后一個語句是表達式,則返回其值。
以下方法也將使用此功能。
給定上面的構造函數, GetIncludePath
成為
sub GetIncludePath {
my( $Packet ) = @_;
my @path = @{ $Packet->{_IncludePath} };
wantarray ? @path : \@path;
}
這里有幾件事情。 首先,請注意我們要小心返回包含路徑的副本,而不是直接引用內部數組。 這樣,用戶可以修改從GetIncludePath
返回的值,而不必擔心丟棄數據包的狀態。
wantarray
運算符允許sub確定其調用的上下文並相應地做出響應。 在列表上下文中, GetIncludePath
將返回數組中的值列表。 否則,它返回對數組副本的引用。 這樣,客戶端代碼可以像在中一樣調用它
foreach my $path (@{ $packet->GetIncludePath }) { ... }
要么
foreach my $path ($packet->GetIncludePath) { ... }
SetIncludePath
是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
減少打字的另一種方法是使用Moose。
package Packet;
use Moose::Policy 'Moose::Policy::JavaAccessors';
use Moose;
has 'PacketName' => (
is => 'rw',
isa => 'Str',
required => 1,
);
has 'Platform' => (
is => 'rw',
isa => 'Str',
required => 1,
);
has 'Version' => (
is => 'rw',
isa => 'Int',
required => 1,
);
has 'IncludePath' => (
is => 'ro',
isa => 'ArrayRef[Str]',
default => sub {[]},
traits => [ 'Array' ],
handles => {
getIncludePath => 'elements',
getIncludePathMember => 'get',
setIncludePathMember => 'set',
},
);
__PACKAGE__->meta->make_immutable;
no Moose;
1;
查看Moose :: Manual :: Unsweetened ,了解Moose如何節省時間的另一個例子。
如果您堅持學習經典Perl OOP的願望,請閱讀以下perldoc文章: perlboot , perltoot , perlfreftut和perldsc 。
一本關於經典Perl OO的好書是Damian Conway的面向對象Perl 。 它將讓您了解Perl對象的可能性。
一旦你理解了@ gbacon的答案 ,就可以使用Class :: Accessor :: Fast保存一些輸入:
#!/usr/bin/perl
package My::Class;
use strict; use warnings;
use base 'Class::Accessor::Fast';
__PACKAGE__->follow_best_practice;
__PACKAGE__->mk_accessors( qw(
IncludePath
PacketName
Platform
Version
));
use overload '""' => 'to_string';
sub to_string {
my $self = shift;
sprintf(
"%s [ %s:%s ]: %s",
$self->get_PacketName,
$self->get_Platform,
$self->get_Version,
join(':', @{ $self->get_IncludePath })
);
}
my $obj = My::Class->new({
PacketName => 'dummy', Platform => 'Linux'
});
$obj->set_IncludePath([ qw( /home/include /opt/include )]);
$obj->set_Version( '1.05b' );
print "$obj\n";
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.