您可以使用MooseX::Role::Parameterized:
Favorites.pm
package Favorites;
use MooseX::Role::Parameterized;
parameter method_name => (
isa => 'Str',
default => 'favorite_things'
);
role {
my $p = shift;
my %args = @_;
my $consumer = $args{consumer};
my $method_name = $p->method_name;
my @default_values = qw/doorbells sleighbells/;
if ( $consumer->find_method_by_name($method_name) ) {
around $method_name => sub {
my $orig = shift;
my $self = shift;
$self->$orig(@_), @default_values;
};
}
else {
method $method_name => sub {
my $self = shift;
return @default_values;
};
}
};
no Moose::Role;
1;
Santa.pm(圣诞老人喜欢门铃,对吧?):
package Santa;
use Moose;
use namespace::autoclean;
with 'Favorites';
__PACKAGE__->meta->make_immutable;
1;
ACDC.pm
package ACDC;
use Moose;
use namespace::autoclean;
with 'Favorites';
sub favorite_things {
my $self = shift;
return 'Hells Bells';
}
__PACKAGE__->meta->make_immutable;
1;
favorites_test
use strict;
use warnings;
use 5.010;
use ACDC;
use Santa;
my $kris_kringle = Santa->new;
say 'Santa likes ', join(', ', $kris_kringle->favorite_things);
my $acdc = ACDC->new;
say 'AC/DC likes ', join(', ', $acdc->favorite_things);
输出:
Santa likes doorbells, sleighbells
AC/DC likes Hells Bells, doorbells, sleighbells
请注意,如果您的角色被另一个参数化角色使用,或者如果您的角色应用于对象实例,则您必须执行额外的操作。 Ether 在 How can I access the meta class of the module my Moose role is being applied to? 中描述了这两种情况,并在评论中指出:
我不再认为上述是“最佳实践”,并且确实已经重构了所有这些(ab)对 MXRP 的使用。恕我直言,如果您需要在某个角色中访问 $meta,那么您的设计中就有一些臭名昭著的东西。
您有什么理由不能简单地将favorite_things 设为必需?