You could do this using 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 (Santa likes doorbells, right?):
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);
Output:
Santa likes doorbells, sleighbells
AC/DC likes Hells Bells, doorbells, sleighbells
Note that you have to do additional gymnastics if your role is consumed by another parameterized role, or if your role is applied to an object instance. Ether describes both of these cases in How can I access the meta class of the module my Moose role is being applied to? and notes in a comment that:
I no longer consider the above a "best practice", and indeed have refactored out all of this (ab)use of MXRP. IMHO if you need to access $meta
from within a role, you have something stinky in your design.
Is there any reason you can't simply make favorite_things
required?