在Perl中如何使用数组作为对象属性?
我需要一些关于Perl中数组的帮助 这是我的构造函数 下午六时在Perl中如何使用数组作为对象属性?,perl,arrays,constructor,Perl,Arrays,Constructor,我需要一些关于Perl中数组的帮助 这是我的构造函数 下午六时 sub new { my $class = shift; my $Packet = { _PacketName => shift, _Platform => shift, _Version => shift, _Inclu
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文件读取IncludePath并将其推送到该数组中
# 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是一个数组,我无法使它工作,我的意思是没有打印相对路径。如果启用严格的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. 请注意,无需将祝福对象存储在临时变量中,然后立即返回它,因为: 如果未找到
return
,并且如果最后一条语句是表达式,则返回其值
下面的方法也将利用此功能
给定上面的构造函数,GetIncludePath
变为
sub GetIncludePath {
my( $Packet ) = @_;
my @path = @{ $Packet->{_IncludePath} };
wantarray ? @path : \@path;
}
这里发生了几件事。首先,请注意,我们小心地返回include路径的副本,而不是直接引用内部数组。这样,用户就可以修改从GetIncludePath
返回的值,而不必担心数据包的状态会变糟
允许sub确定其调用的上下文并相应地响应。在列表上下文中,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
我的名字
-[富]
-[酒吧]
-[baz]
我的名字
-[./input/myMockPacketName]
-[./input/myPacket/my3/*.txt]
-[./input/myPacket/in.html]
在标量上下文中:
./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;
查看关于驼鹿如何节省时间的另一个例子
如果您对学习经典Perl OOP有着坚定的愿望,请阅读以下文章:、和
这是一本关于经典PerlOO的好书。它将让您了解Perl对象中的可能性。我尝试实现这些更改,并尝试从GetIncludePath打印数组@{$Packet->{u IncludePath},结果显示出来nothing@superstar数组最初将为空,因为构造函数中的
my@includeobjects=()
创建了一个新的空数组。像$packet->SetIncludePath(qw/foo-bar-baz/)
这样的代码会给它一个有趣的值。你在测试中做过吗?我实际上使用的是$newPacket->SetIncludePath(@includeobjects);在另一个传递IncludeObject数组的模块中,我应该在GetIncludePath中获取这些数组值,但这并没有发生。@brian d foy:当我调用$packet->GetIncludePath时,我应该能够获得从SetIncludePath设置的数组值…对吗?@superstar查看更新答案中存储和检索include路径的工作示例。你的代码有什么不同?我的眼睛。为什么不使用use strict;使用警告代码>?感谢您指出!!现在我正在使用它们。:)@includeobjects
的赋值有一个语法错误,根本不允许您的程序运行(您可以将其更改为@includeobjects=qw[./input/myMockPacketName./input/myPacket/my3/*.txt./input/myPacket/in.html];
)。请复制并粘贴,这样我们就可以帮助您修复代码,而不是猜测它可能是什么。您添加的代码还包含语法错误:push(@includeobjects,$value)
周围缺少大括号。复制并粘贴代码,而不是重新键入代码,这一点很重要。我修改了我的答案,使用了与您相同的@includeobjects
,输出看起来很好。你已经告诉我们你没有得到的输出,那么你得到了什么?这也是重要的信息!我想我看到了问题所在。PacketInput.pm
是否启用了strict
pragmaGetIncludePath
返回一个数组,但CreateStringPath
具有@{$packet->GetIncludePath()}
,它将其视为对数组的引用。我将修改我的答案,使GetIncludePath
在使用wantarray
返回值时更加智能。如果Moos-eis完全不可能的话,Class::Accessor是一个合理的选择。但是驼鹿很厉害。谢谢你的文档和这本书,没有任何关于驼鹿的建议,但我不会说它的好处之一是减少打字。我认为这太冗长了,希望有一天它能从类的文本描述中生成Moose代码。@brian,这是一个有趣的想法。IME、Moose可能很冗长,但它比编写经典的PerlOOP类要紧凑得多。类型、强制和方法生成带来了巨大的节约。但我希望对象声明使用不那么冗长的标点语法。
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
#!/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";
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;