我如何订购一个类的哈希成员?我的课看起来像这样
package TestSuiteInterface {
use Tie::IxHash;
sub new {
my ($class, $name) = @_;
my $self = {};
my %schedulerdata = {};
tie(%schedulerdata, 'Tie::IxHash');
$self->{name} = $name;
$self->{scheduler} = %schedulerdata;
bless $self, $class;
return $self;
}
sub getVariables {
my ($self) = shift;
return $self->{variables}
}
sub loadtests {
my ($self) = shift;
{
#tie(my %data, 'Tie::IxHash');
#%data = %{$self->{scheduler}};
my @scheduler = values %{$self->{scheduler}};
#die "oops" unless $self->{scheduler}
$_->() for (@scheduler);
return 1;
}
return 0;
}
}
以上,我尝试使用Tie :: IxHash。我试图弄清楚如何为$ self-> {scheduler}做到这一点,稍后子类将添加项。例如
package Test {
use base 'TestSuiteInterface';
use main_common;
sub new {
my ($class, $name) = @_;
my $self = {};
class->SUPER::new($name);
$self->{variables}={};
$self->{scheduler} = {
boot_linuxrc => sub{ loadtest("boot/boot_linuxrc"); },
first_boot => sub{ loadtest("installation/first_boot");}
};
bless $self, $class;
return $self;
}
}
要使用Tie :: IxHash,我必须在设置变量之前使用它,对吗?因此,最后在负载测试中使用它是没有用的。我可以在构造函数中执行此操作,还是可以在循环内按顺序取回$ self-> {scheduler}?
在new()
方法中,创建一个Tie :: IxHash对象并将其存储在测试对象中。
my %schedulerdata = {};
tie(%schedulerdata, 'Tie::IxHash');
...
$self->{scheduler} = %schedulerdata;
实际上,那里有一些小错误。首先,您使用哈希引用初始化哈希。
my %schedulerdata = {};
真的,您想使用一个空列表初始化它:
my %schedulerdata = ();
或者,更好的是,仅依靠Perl将其初始化为空哈希。
my %schedulerdata;
然后,您尝试将哈希存储在对象中。但是对象属性只能是标量,因此您需要在对象中存储对哈希的引用。
$self->{scheduler} = \%schedulerdata;
将所有内容放在一起,构造函数方法应如下所示:
sub new {
my ($class, $name) = @_;
my $self = {};
my %schedulerdata;
tie(%schedulerdata, 'Tie::IxHash');
$self->{name} = $name;
$self->{scheduler} = \%schedulerdata;
bless $self, $class;
return $self;
}
但是这些问题并不是导致此问题不起作用的原因。稍后,当您为调度程序提供值时。您的代码如下所示:
$self->{scheduler} = {
boot_linuxrc => sub{ loadtest("boot/boot_linuxrc"); },
first_boot => sub{ loadtest("installation/first_boot"); }
};
但是想想这是怎么回事。您正在创建一个全新的匿名哈希,并将对该哈希的引用存储在对象中。这将覆盖您精心构造的绑定哈希,然后将其替换为标准(非绑定)哈希。
为了保留哈希的束缚特性,您需要向其添加键/值对-而不是完全覆盖它。我认为这样的代码会起作用。
$self->{scheduler}->{boot_linuxrc} = sub{ loadtest("boot/boot_linuxrc"); };
$self->{scheduler}->{first_boot} = sub{ loadtest("installation/first_boot"); };
注意:如果您的代码包含use warnings
(Perl代码应始终包含[C0]),则该行:
use warnings
将触发警告:
参考找到期望的大小均匀的列表
这就是为什么我们总是建议包括my %schedulerdata = {};
:-)
最后,我的解决方案是不使用Tie :: IxHash。相反,我使用了一个单独的函数来获取有序列表,并将其分配给实例成员。我将以另一种方式发布它,因为@Dave Cross的解决方案仍然是正确的。
use warnings
@ list现在包含4个元素。 [boot_linuxrc,sub {loadtest(“ boot / boot_linuxrc”)},first_boot,sub {loadtest(“ installation / first_boot”)}]。在示例中,set_scheduler使用map使用@list的索引[1]和[3]为我提供了一个子列表。 0 ..(@list / 2)-1是在@order中获得正确的大小(2个项目)。
我用使用以下项的代码波纹管替换了[[package Test中的以前的$ self-> {scheduler}] >>sub set_scheduler {
 my ($self, @list) = @_;
 # get a list of the subroutines of the hash
 my @order = map { $list[($_ * 2) + 1] } 0 .. (@list / 2) - 1;
 my %schedule = @list;
 $self->{scheduler} = \%schedule;
 $self->{scheduler_order} = \@order;
 return $self;
 }
然后,我在负载测试中运行以下命令
$self->set_scheduler(
boot_linuxrc => sub { loadtest("boot/boot_linuxrc") },
installer_extended => sub { loadtest("installation/first_boot") }
);
感谢@DaveCross