diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-06-06 17:50:16 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-06-06 17:50:16 +0000 |
commit | 5ac2026f7eed78958d69d051e7a8e993dcf51205 (patch) | |
tree | 298c3d2f08bdfe5689998b11892d72a897985be1 /lib/Moose/Cookbook/Roles/Restartable_AdvancedComposition.pod | |
download | Moose-tarball-5ac2026f7eed78958d69d051e7a8e993dcf51205.tar.gz |
Moose-2.1405HEADMoose-2.1405master
Diffstat (limited to 'lib/Moose/Cookbook/Roles/Restartable_AdvancedComposition.pod')
-rw-r--r-- | lib/Moose/Cookbook/Roles/Restartable_AdvancedComposition.pod | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/lib/Moose/Cookbook/Roles/Restartable_AdvancedComposition.pod b/lib/Moose/Cookbook/Roles/Restartable_AdvancedComposition.pod new file mode 100644 index 0000000..53069a2 --- /dev/null +++ b/lib/Moose/Cookbook/Roles/Restartable_AdvancedComposition.pod @@ -0,0 +1,230 @@ +# 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.1405 + +=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<Restartable> +role which provides an C<is_paused> attribute, and two methods, +C<stop> and C<start>. + +Then we have two more roles which implement the same interface, each +putting their own spin on the C<stop> and C<start> methods. + +In the C<Restartable::ButUnreliable> role, we want to provide a new +implementation of C<stop> and C<start>, but still have access to the +original implementation. To do this, we alias the methods from +C<Restartable> to private methods, and provide wrappers around the +originals (1). + +Note that aliasing simply I<adds> 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<Restartable::ButBroken> role, we want to provide an entirely +new behavior for C<stop> and C<start>. We exclude them entirely when +composing the C<Restartable> role into C<Restartable::ButBroken>. + +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<Restartable> 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 <stevan.little@iinteractive.com> + +=item * + +Dave Rolsky <autarch@urth.org> + +=item * + +Jesse Luehrs <doy@tozt.net> + +=item * + +Shawn M Moore <code@sartak.org> + +=item * + +יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org> + +=item * + +Karen Etheridge <ether@cpan.org> + +=item * + +Florian Ragwitz <rafl@debian.org> + +=item * + +Hans Dieter Pearcey <hdp@weftsoar.net> + +=item * + +Chris Prather <chris@prather.org> + +=item * + +Matt S Trout <mst@shadowcat.co.uk> + +=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 |