您可以将哈希值的哈希值存储在 Moose 对象中,其方式与存储任何其他哈希值几乎相同:
has steps => ( is => 'ro', isa => 'HashRef' );
但是,您可以更具体地将其声明为需要存储的特定类型的哈希值,以验证存储在该槽中的任何内容是否正确:
has steps => ( is => 'ro', isa => 'HashRef[HashRef[Object]]' );
根据数据,我也可能会改变Object
这里是类名。您可以变得更喜欢并使用MooseX::类型 https://metacpan.org/module/MooseX::Types::Structured and MooseX::类型::结构化 https://metacpan.org/module/MooseX::Types::Structured指定更严格的结构。
至于帮助者跨过你的结构,我不知道 Moose 或 MooseX 中有什么可以做到这一点。如果您知道数据的结构,那么最好自己实现一个子例程来完成您需要的操作。与任何通用遍历相比,您的代码可能会表现得更好,并且可以更好地完成您需要的事情。
编辑/附加信息:每个 Moose 属性都会在您的类中创建一个访问器方法,该方法返回存储的值,因此访问数据是:
# Assuming we put the attribute in a package named StepTool
my $step_tool = StepTool->new(
steps => { 'step1' => {'extraction' => \$object1,
'analysis' => \$object2},
'step2' => {'extraction' => \$object3,
'analysis' => \$object4} },
);
# To do something one of the values
do_something($step_tool->steps->{step1}{extraction});
# To iterate over the structure, could be done in a method on StepTool
for my $step_name (keys %{ $step_tool->steps }) {
my $step = $step_tool->steps->{ $step_name };
for my $action_name (keys %$step) {
my $object = $step->{ $action_name };
do_something($object);
}
}
# If doing the above as a method, $self is the Moose object, so...
sub traverse_steps {
my ($self) = @_;
for my $step_name (keys %{ $self->steps }) {
... # just like above
}
}
另请注意,您仍然可以使用traits => [ 'Hash' ]
如果你愿意的话,添加一些手柄来给自己一些额外的帮助。
如果数据结构比这更自由,您可能需要研究类似的内容数据::访客 https://metacpan.org/module/Data::Visitor迭代子例程中的结构。 (我在 Data::Visitor 上遇到了一些难以调试、奇怪的问题,所以我尽量避免它。)