我当然知道我可以通过设置init_arg
(例如)重命名属性的init arg
package Test {
use Moose;
has attr => (
is => 'ro',
isa => 'Str',
init_arg => 'attribute'
);
}
这将允许我
Test->new({ attribute => 'foo' });
但不是
Test->new({ attr => 'foo' });
同时
MooseX::Aliases实际上有这种行为,但是创建别名也会创建访问器。我目前正在尝试理解该模块中的代码,看看我是否无法确定它是如何做到的,以便我可以复制所述功能(以我理解的方式)。如果有人可以用一个例子来解释如何在这里做到这一点,那就太好了。
更新似乎 MX::Aliases 正在通过替换实际传递给构造函数的内容来执行此操作,around initialize_instance_slot
但我仍然不确定它实际上是如何被调用的,因为在我的测试代码中,我的周围实际上并没有被执行。
update munging inBUILDARGS
并不是一个真正的选项,因为我正在尝试做的事情是允许通过我通过Meta Recipe3添加到属性的标签名称来设置访问器。你可能会说我在做
has attr => (
is => 'ro',
isa => 'Str',
alt_init_arg => 'attribute'
);
更新
到目前为止,我已经设法解决了我正在尝试做的事情。
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
问题是我的around
块永远不会被运行,我不知道为什么,也许我把它包装在错误的地方或什么地方。