¿Cómo puedo proporcionar un init arg alternativo para un atributo en Moose?

Por supuesto, sé que puedo cambiar el nombre de init arg para un atributo configurandoinit_arg (p.ej)

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

lo que me permitiría

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

pero no

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

al mismo tiempo

MooseX :: Alias en realidad tiene este comportamiento, pero crear un alias también crea accesores. Actualmente estoy tratando de entender el código en ese módulo para ver si no puedo determinar cómo lo hace, para poder replicar dicha funcionalidad (de una manera que entiendo). Si alguien pudiera explicar cómo hacerlo aquí con un ejemplo sería genial.

actualizar parece que MX :: Aliases está haciendo esto para reemplazar lo que realmente se pasa al constructor en unaaround initialize_instance_slot pero todavía no estoy seguro de cómo se está llamando, porque en mi código de prueba no se está ejecutando realmente a mi alrededor.

actualizar munging enBUILDARGS no es realmente una opción porque lo que estoy tratando de hacer permite la configuración del elemento de acceso a través del nombre deletiqueta Estoy agregando al atributo a través deMeta Receta 3. Podrias decir que estoy haciendo

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

actualizar

Esto es lo que he logrado resolver con lo que estoy tratando de hacer hasta ahora.

<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>

El problema es que miaround el bloque nunca se ejecuta y no estoy seguro de por qué, tal vez lo estoy envolviendo en el lugar equivocado o algo así.

Respuestas a la pregunta(3)

Su respuesta a la pregunta