v0.01
[gitmo/Moose-OldDocs.git] / lib / Moose / Cookbook / Roles / Recipe2.pod
CommitLineData
4472117d 1package Moose::Cookbook::Roles::Recipe2;
2
3# ABSTRACT: Advanced Role Composition - method exclusion and aliasing
4
5__END__
6
7
8=pod
9
10=head1 SYNOPSIS
11
12 package Restartable;
13 use Moose::Role;
14
15 has 'is_paused' => (
16 is => 'rw',
17 isa => 'Bool',
18 default => 0,
19 );
20
21 requires 'save_state', 'load_state';
22
23 sub stop { 1 }
24
25 sub start { 1 }
26
27 package Restartable::ButUnreliable;
28 use Moose::Role;
29
30 with 'Restartable' => {
31 -alias => {
32 stop => '_stop',
33 start => '_start'
34 },
35 -excludes => [ 'stop', 'start' ],
36 };
37
38 sub stop {
39 my $self = shift;
40
41 $self->explode() if rand(1) > .5;
42
43 $self->_stop();
44 }
45
46 sub start {
47 my $self = shift;
48
49 $self->explode() if rand(1) > .5;
50
51 $self->_start();
52 }
53
54 package Restartable::ButBroken;
55 use Moose::Role;
56
57 with 'Restartable' => { -excludes => [ 'stop', 'start' ] };
58
59 sub stop {
60 my $self = shift;
61
62 $self->explode();
63 }
64
65 sub start {
66 my $self = shift;
67
68 $self->explode();
69 }
70
71=head1 DESCRIPTION
72
73In this example, we demonstrate how to exercise fine-grained control
74over what methods we consume from a role. We have a C<Restartable>
75role which provides an C<is_paused> attribute, and two methods,
76C<stop> and C<start>.
77
78Then we have two more roles which implement the same interface, each
79putting their own spin on the C<stop> and C<start> methods.
80
81In the C<Restartable::ButUnreliable> role, we want to provide a new
82implementation of C<stop> and C<start>, but still have access to the
83original implementation. To do this, we alias the methods from
84C<Restartable> to private methods, and provide wrappers around the
85originals (1).
86
87Note that aliasing simply I<adds> a name, so we also need to exclude the
88methods with their original names.
89
90 with 'Restartable' => {
91 -alias => {
92 stop => '_stop',
93 start => '_start'
94 },
95 -excludes => [ 'stop', 'start' ],
96 };
97
98In the C<Restartable::ButBroken> role, we want to provide an entirely
99new behavior for C<stop> and C<start>. We exclude them entirely when
100composing the C<Restartable> role into C<Restartable::ButBroken>.
101
102It's worth noting that the C<-excludes> parameter also accepts a single
103string as an argument if you just want to exclude one method.
104
105 with 'Restartable' => { -excludes => [ 'stop', 'start' ] };
106
107=head1 CONCLUSION
108
109Exclusion and renaming are a power tool that can be handy, especially
110when building roles out of other roles. In this example, all of our
111roles implement the C<Restartable> role. Each role provides same API,
112but each has a different implementation under the hood.
113
114You can also use the method aliasing and excluding features when
115composing a role into a class.
116
117=head1 FOOTNOTES
118
119=over 4
120
121=item (1)
122
123The mention of wrapper should tell you that we could do the same thing
124using method modifiers, but for the sake of this example, we don't.
125
126=back
127
128=begin testing
129
130{
131 my $unreliable = Moose::Meta::Class->create_anon_class(
132 superclasses => [],
133 roles => [qw/Restartable::ButUnreliable/],
134 methods => {
135 explode => sub { }, # nop.
136 'save_state' => sub { },
137 'load_state' => sub { },
138 },
139 )->new_object();
140 ok( $unreliable, 'made anon class with Restartable::ButUnreliable role' );
141 can_ok( $unreliable, qw/start stop/ );
142}
143
144{
145 my $cnt = 0;
146 my $broken = Moose::Meta::Class->create_anon_class(
147 superclasses => [],
148 roles => [qw/Restartable::ButBroken/],
149 methods => {
150 explode => sub { $cnt++ },
151 'save_state' => sub { },
152 'load_state' => sub { },
153 },
154 )->new_object();
155
156 ok( $broken, 'made anon class with Restartable::ButBroken role' );
157
158 $broken->start();
159
160 is( $cnt, 1, '... start called explode' );
161
162 $broken->stop();
163
164 is( $cnt, 2, '... stop also called explode' );
165}
166
167=end testing
168
169=cut