# PODNAME: Moose::Cookbook::Roles::Restartable_AdvancedComposition # ABSTRACT: Advanced Role Composition - method exclusion and aliasing __END__ =pod =encoding UTF-8 =head1 NAME Moose::Cookbook::Roles::Restartable_AdvancedComposition - Advanced Role Composition - method exclusion and aliasing =head1 VERSION version 2.2207 =head1 SYNOPSIS package Restartable; use Moose::Role; has 'is_paused' => ( is => 'rw', isa => 'Bool', default => 0, ); requires 'save_state', 'load_state'; sub stop { 1 } sub start { 1 } package Restartable::ButUnreliable; use Moose::Role; with 'Restartable' => { -alias => { stop => '_stop', start => '_start' }, -excludes => [ 'stop', 'start' ], }; sub stop { my $self = shift; $self->explode() if rand(1) > .5; $self->_stop(); } sub start { my $self = shift; $self->explode() if rand(1) > .5; $self->_start(); } package Restartable::ButBroken; use Moose::Role; with 'Restartable' => { -excludes => [ 'stop', 'start' ] }; sub stop { my $self = shift; $self->explode(); } sub start { my $self = shift; $self->explode(); } =head1 DESCRIPTION In this example, we demonstrate how to exercise fine-grained control over what methods we consume from a role. We have a C role which provides an C attribute, and two methods, C and C. Then we have two more roles which implement the same interface, each putting their own spin on the C and C methods. In the C role, we want to provide a new implementation of C and C, but still have access to the original implementation. To do this, we alias the methods from C to private methods, and provide wrappers around the originals (1). Note that aliasing simply I a name, so we also need to exclude the methods with their original names. with 'Restartable' => { -alias => { stop => '_stop', start => '_start' }, -excludes => [ 'stop', 'start' ], }; In the C role, we want to provide an entirely new behavior for C and C. We exclude them entirely when composing the C role into C. It's worth noting that the C<-excludes> parameter also accepts a single string as an argument if you just want to exclude one method. with 'Restartable' => { -excludes => [ 'stop', 'start' ] }; =head1 CONCLUSION Exclusion and renaming are a power tool that can be handy, especially when building roles out of other roles. In this example, all of our roles implement the C role. Each role provides same API, but each has a different implementation under the hood. You can also use the method aliasing and excluding features when composing a role into a class. =head1 FOOTNOTES =over 4 =item (1) The mention of wrapper should tell you that we could do the same thing using method modifiers, but for the sake of this example, we don't. =back =begin testing { my $unreliable = Moose::Meta::Class->create_anon_class( superclasses => [], roles => [qw/Restartable::ButUnreliable/], methods => { explode => sub { }, # nop. 'save_state' => sub { }, 'load_state' => sub { }, }, )->new_object(); ok( $unreliable, 'made anon class with Restartable::ButUnreliable role' ); can_ok( $unreliable, qw/start stop/ ); } { my $cnt = 0; my $broken = Moose::Meta::Class->create_anon_class( superclasses => [], roles => [qw/Restartable::ButBroken/], methods => { explode => sub { $cnt++ }, 'save_state' => sub { }, 'load_state' => sub { }, }, )->new_object(); ok( $broken, 'made anon class with Restartable::ButBroken role' ); $broken->start(); is( $cnt, 1, '... start called explode' ); $broken->stop(); is( $cnt, 2, '... stop also called explode' ); } =end testing =head1 AUTHORS =over 4 =item * Stevan Little =item * Dave Rolsky =item * Jesse Luehrs =item * Shawn M Moore =item * יובל קוג'מן (Yuval Kogman) =item * Karen Etheridge =item * Florian Ragwitz =item * Hans Dieter Pearcey =item * Chris Prather =item * Matt S Trout =back =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2006 by Infinity Interactive, Inc. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut