I have WrapperClass object that has an InnerClass object as an attribute. The InnerClass object has a weight attribute. My WrapperClass object also has a weight attribute and I want its default value to be whatever the value of the InnerClass object's weight attribute is.
#!/usr/bin/perl
package InnerClass;
use Moose;
has 'weight' => (
is => 'rw',
);
package WrapperClass;
use Moose;
has 'wrapped' => (
is => 'rw',
lazy => 1,
default => sub {InnerClass->new(weight => 1)},
);
has 'weight' => (
is => 'rw',
default => sub {
my $self = shift;
$self->wrapped->weight()
},
lazy => 1,
);
The code above works, but in reality InnerClass has many attributes which WrapperClass needs to do the same thing for. Ideally I would do something like this when I'm writing WrapperClass:
use Moose;
has 'wrapped' => (
is => 'rw',
);
my @getDefaultsFromWrappers
= qw(weight height mass x y z label); # etc ...
foreach my $attr (@getDefaultsFromWrappers) {
has $attr => (
is => 'rw',
default => sub {
# Somehow tell the default which attribute
# it needs to call from wrapped object?
my $self = shift;
$self->wrapped->???()
},
lazy => 1,
);
}
However, there is no way of passing an argument to a default or builder to tell it which attribute it is building. I've considered using caller
but this seems like a hack.
Does anyone know how I could accomplish this style of attribute declaration or is it a case of declaring each attribute and its default separately?
You can use
$attr
where your question marks are because it is still in scope when you declare the attributes.The following is a possible alternative, which you might want to use if your attribute declarations are not uniform: