我想知道,在Moose中存储Hash of Hash的最好方法是什么?让我们以下面这样的Hash为例:
my %hash = ('step1' => {'extraction' => \$object1,
'analysis' => \$object2},
'step2' => {'extraction' => \$object3,
'analysis' => \$object4});但是我想把它保存在一个驼鹿属性中。我应该如何组织对此的访问(读、写)。网上的例子大多是针对“平面”散列的。但是你可以使用像Moose::Meta::Attribute::Native::::Hash这样的帮助器。散列的散列也有类似的东西吗?
这样做的原因是,我想迭代步骤键并访问其中的对象实例。或者有没有一种更好、更像驼鹿的方式来做到这一点?
提前感谢!
发布于 2012-08-02 19:38:14
您可以在Moose对象中存储散列的散列,其方式与存储任何其他散列的方式几乎相同:
has steps => ( is => 'ro', isa => 'HashRef' );但是,您可以更具体地将其声明为您需要存储的特定类型的散列,以此来验证存储在该插槽中的任何内容是否正确:
has steps => ( is => 'ro', isa => 'HashRef[HashRef[Object]]' );根据数据的不同,我可能还会将此处的Object更改为类名。您可以使用MooseX::Types和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' ]并添加一些句柄来为自己提供一些额外的帮助器。
如果数据结构比这更自由,那么您可能需要查看类似于Data::Visitor的内容,以便在子例程中迭代您的结构。(我遇到了一些难以调试的奇怪的Data::Visitor问题,所以我尽量避免它。)
发布于 2015-01-26 03:23:25
还有一种受Moose: How to get an array of objects? Traits?启发的类型安全方法。
有一个类用来保存具有traits => ['Hash']的外部散列(StepTool::Steps)。这种方法可以使用Array和Hashes进行无限深度的嵌套:
package StepTool;
use Moose;
has 'steps' => (
'is' => 'rw',
'isa' => 'StepTool::Steps',
'default' => sub { StepTool::Steps->new() },
);
package StepTool::Steps;
use Mouse;
has '_steps' => (
is => 'ro',
isa => 'HashRef[StepTool::Step]',
traits => ['Hash'],
default => sub { {} },
handles => {
# You'll probably want a fuller set here...
get => 'get',
set => 'set',
keys => 'keys',
}
);
package StepTool::Step;
use Mouse;
has 'extraction' => (
is => 'rw',
);
has 'analysis' => (
is => 'rw',
);
package main;
my $object1 = bless {}, 'Foobar1';
my $object2 = bless {}, 'Foobar2';
my $object3 = bless {}, 'Foobar3';
my $object4 = bless {}, 'Foobar4';
my $stepTool = StepTool->new();
# set up step1 one field at a time.
$stepTool->steps->set('step1', StepTool::Step->new());
# I have no idea why the OP wants references to objects
# everywhere but he does...
$stepTool->steps->get('step1')->extraction(\$object1);
$stepTool->steps->get('step1')->analysis(\$object2);
# set up step2 all at once
$stepTool->steps->set('step2', StepTool::Step->new(
extraction => \$object3,
analysis => \$object4
));
# or, less elegantly, initialize an entire StepTool:
my $stepTool2 = StepTool->new(
steps => StepTool::Steps->new(
_steps => {
step1 => StepTool::Step->new(
extraction => \$object1,
analysis => \$object2
),
step2 => StepTool::Step->new(
extraction => \$object3,
analysis => \$object4
),
}
),
);
printf "step1->analysis is a ref to an instance of class: %s\n",
ref(${$stepTool->steps->get('step1')->analysis});https://stackoverflow.com/questions/11776184
复制相似问题