Аргумент для подпрограммы строителя в объекте лося

В настоящее время я делегирую метод Builder всем объектам, расширяющим один из моих базовых классов. Проблема, с которой я столкнулся, заключается в том, что мне нужно, чтобы все объекты либо читали атрибуты самих себя, либо передавались в значении.

#  In Role:
has 'const_string' => (
    isa     => 'Str',
    is      => 'ro',
    default => 'test',
);

has 'attr' => (
    isa     => 'Str',
    is      => 'ro',
    builder => '_builder',
);

requires '_builder';


#  In extending object  -  desired 1
sub _builder {
    my ($self) = shift;
    #  $self contains $self->const_string
 }

#  In extending object  -  desired 2
sub _builder {
    my ($arg1, $arg2) = @_;
    #  $args can be passed somehow?
 }

Возможно ли это в настоящее время или мне придется сделать это каким-то другим способом?


person lespea    schedule 20.07.2010    source источник
comment
Мне трудно понять, чего именно вы пытаетесь достичь, возможно, объясните это с точки зрения потребителя?   -  person Kent Fredric    schedule 20.07.2010


Ответы (2)


Вы не можете передавать аргументы в методы построения атрибутов. Они автоматически вызываются внутренними компонентами Moose и передают только один аргумент — саму ссылку на объект. Построитель должен иметь возможность вернуть свое значение на основе того, что он видит в $self, или что-то еще в среде, к которой у него есть доступ.

Какие аргументы вы хотели бы передать застройщику? Можете ли вы вместо этого передать эти значения конструктору объекта и сохранить их в других атрибутах?

# in object #2:
has other_attr_a => (
    is => 'ro', isa => 'Str',
);
has other_attr_b => (
    is => 'ro', isa => 'Str',
);

sub _builder
{
    my $self = shift;
    # calculates something based on other_attr_a and other_attr_b
}

# object #2 is constructed as:
my $obj = Class2->new(other_attr_a => 'value', other_attr_b => 'value');

Также обратите внимание, что если у вас есть атрибуты, построенные на основе других значений атрибутов, вы должны определить их как lazy, иначе строители/значения по умолчанию будут запускаться сразу при построении объекта и в неопределенном порядке. Установка для них ленивых задержит их определение до тех пор, пока они не потребуются в первую очередь.

person Ether    schedule 20.07.2010
comment
Мне просто нужно было установить lazy, и все получилось отлично. В моем первоначальном тестировании у меня не было этого набора, поэтому я не мог видеть другие атрибуты в моем методе сборки. Спасибо! - person lespea; 20.07.2010

Вы можете сделать что-то вроде этого:

has 'attr' => (
isa     => 'Str',
is      => 'ro',
builder => '_pre_builder',
);

sub pre_builder {
  _builder(@_, 'your_arg');
}
person StevieD    schedule 22.03.2016