Como posso fornecer um init arg alternativo para um atributo no Moose?

É claro que sei que posso renomear o arg de init para um atributo, definindoinit_arg (por exemplo)

<code>package Test {
    use Moose;
    has attr => (
       is => 'ro',
       isa => 'Str',
       init_arg => 'attribute'
    );
}
</code>

o que me permitiria

<code>Test->new({ attribute => 'foo' });
</code>

mas não

<code>Test->new({ attr => 'foo' });
</code>

ao mesmo tempo

MooseX :: Aliases na verdade tem esse comportamento, mas a criação de um alias também cria acessores. No momento, estou tentando entender o código desse módulo para ver se não consigo determinar como ele faz isso, para que eu possa replicar essa funcionalidade (de uma maneira que eu entenda). Se alguém pudesse explicar como fazer isso aqui com um exemplo seria ótimo.

atualizar parece que o MX :: Aliases está fazendo isso substituindo o que é realmente passado para o construtor em umaround initialize_instance_slot mas eu ainda não tenho certeza de como isso realmente está sendo chamado, porque no meu código de teste a minha volta não está sendo executada.

atualizar Munging emBUILDARGS não é realmente uma opção, porque o que estou tentando fazer permite a configuração do acessador através do nome dorótulo Estou adicionando ao atributo viaMeta Recipe3. Você pode dizer que estou fazendo

<code>has attr => (
   is => 'ro',
   isa => 'Str',
   alt_init_arg => 'attribute'
);
</code>

atualizar

aqui está o que eu consegui resolver com o que estou tentando fazer até agora.

<code>use 5.014;
use warnings;

package MooseX::Meta::Attribute::Trait::OtherName {
    use Moose::Role;
    use Carp;

    has other_name => (
        isa       => 'Str',
        predicate => 'has_other_name',
        required  => 1,
        is        => 'ro',
    );

    around initialize_instance_slot => sub {
        my $orig = shift;
        my $self = shift;

        my ( $meta_instance, $instance, $params ) = @_;

        confess 'actually calling this code';

        return $self->$orig(@_)
            unless $self->has_other_name && $self->has_init_arg;

        if ( $self->has_other_name ) {
            $params->{ $self->init_arg }
                = delete $params->{ $self->other_name };
        }
    };
}

package Moose::Meta::Attribute::Custom::Trait::OtherName {
    sub register_implementation { 'MooseX::Meta::Attribute::Trait::OtherName' }
}

package Message {
    use Moose;
#   use MooseX::StrictConstructor;

    has attr => (
        traits    => [ 'OtherName' ],
        is        => 'ro',
        isa       => 'Str',
        other_name => 'Attr',
    );

    __PACKAGE__->meta->make_immutable;
}

package Client {
    use Moose;

    sub serialize {
        my ( $self, $message ) = @_;

        confess 'no message' unless defined $message;

        my %h;
        foreach my $attr ( $message->meta->get_all_attributes ) {
            if (
                    $attr->does('MooseX::Meta::Attribute::Trait::OtherName')
                    && $attr->has_other_name
                ) {
                $h{$attr->other_name} = $attr->get_value( $message );
            }
        }
        return \%h;
    }
    __PACKAGE__->meta->make_immutable;
}

my $message = Message->new( Attr => 'foo' );

my $ua = Client->new;

my %h = %{ $ua->serialize( $message )};

use Data::Dumper::Concise;

say Dumper \%h
</code>

problema é que meuaround bloco nunca está sendo executado e eu não tenho certeza porque, talvez eu estou embrulhando no lugar errado ou algo assim.

questionAnswers(3)

yourAnswerToTheQuestion