Wie kann ich ein alternatives Init-Argument für ein Attribut in Moose bereitstellen?

Ich weiß natürlich, dass ich das Init-Argument für ein Attribut durch Setzen umbenennen kanninit_arg (z.B)

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

das würde mir erlauben

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

aber nicht

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

zur selben Zeit

MooseX :: Aliase hat dieses Verhalten tatsächlich aber das Erstellen eines Alias ​​erstellt auch Accessoren. Ich versuche derzeit, den Code in diesem Modul zu verstehen, um festzustellen, ob ich nicht feststellen kann, wie er funktioniert, damit ich die genannte Funktionalität (auf eine Art und Weise, die ich verstehe) replizieren kann. Wenn hier jemand erklären könnte, wie es geht, wäre das ein großartiges Beispiel.

aktualisieren Es scheint, dass MX :: Aliases dies tut, indem es das ersetzt, was tatsächlich an den Konstruktor in einem übergeben wirdaround initialize_instance_slot aber ich bin mir immer noch nicht sicher, wie das eigentlich heißt, weil in meinem Testcode meine Umgebung eigentlich nicht ausgeführt wird.

aktualisieren einmischenBUILDARGS ist nicht wirklich eine Option, weil das, was ich versuche, die Einstellung des Accessors über den Namen des zulässtEtikette Ich füge dem Attribut über hinzuMeta-Rezept3. Du könntest sagen, dass ich es tue

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

aktualisieren

Ich habe es geschafft, mit dem, was ich bisher versucht habe, zu arbeiten.

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

Das Problem ist, dass meinearound Block wird nie ausgeführt, und ich bin mir nicht sicher, warum. Vielleicht wickle ich ihn an der falschen Stelle ein oder so.

Antworten auf die Frage(3)

Ihre Antwort auf die Frage