Как определить в конструкторе Moose, в каком контексте он вызывался? - PullRequest
2 голосов
/ 09 февраля 2020

Допустим, у нас есть класс Moose, подобный так:

package My::Test ;
use Moose ;
$\="\n";

sub BUILDARGS {
    my ($pkg,%args) = @_ ;
    print defined wantarray ? 'BUILDARGS: SCALAR':'BUILDARGS: VOID' ;
    return \%args ;
}

sub BUILD {
    print defined wantarray ? 'BUILD: SCALAR':'BUILD: VOID' ;
    my ( $self, $args ) = @_ ;
    print '---' ;
}
1;

Создавая класс в контексте SCALAR и VOID, я получаю всегда один и тот же вывод:

#!/usr/bin/perl
use Moose ;
use My::Test ;
# Scalar ctx
my $instance = My::Test->new ;
# Void ctx
My::Test->new ;

Вывод:

BUILDARGS: SCALAR
BUILD: VOID
---
BUILDARGS: SCALAR
BUILD: VOID

Мне удалось получить контекст, обертывающий создание экземпляра класса Moose в тривиальный пакет и передававший контекст как атрибут конструктора следующим образом:

package My::Wrapper ;
use My::Test ;
sub new {
    my ( $class , %args ) = @_ ;
    return My::Test->new(%args , ctx => defined wantarray ? 'scalar':'void') ;
} 
1 ;    

, но я хотел бы знать если есть более чистый способ сделать это.

1 Ответ

6 голосов
/ 09 февраля 2020

Moose создает конструктор для вас (см. здесь ). Контекст не распространяется ни на BUILDARGS, ни на BUILD.

Вы можете обернуть new способом Moose, однако:

around new => sub {
    my ($orig, $self) = splice @_, 0, 2;
    warn defined wantarray ? 'other' : 'void';
    $self->$orig(@_)
};
...