Commit | Line | Data |
2e3d0a0a |
1 | |
2 | =pod |
3 | |
4 | =head1 NAME |
5 | |
6 | Moose::Cookbook::Recipe11 - Advanced Role Composition - method exclusion and aliasing |
7 | |
8 | =head1 SYNOPSIS |
9 | |
10 | package Restartable; |
11 | use Moose::Role; |
12 | |
13 | has 'is_paused' => ( |
14 | is => 'rw', |
15 | isa => 'Boo', |
16 | default => 0, |
17 | ); |
18 | |
19 | requires 'save_state', 'load_state'; |
20 | |
21 | sub stop { ... } |
22 | |
23 | sub start { ... } |
24 | |
25 | package Restartable::ButUnreliable; |
26 | use Moose::Role; |
27 | |
28 | with 'Restartable' => { alias => { stop => '_stop', |
29 | start => '_start' } }; |
30 | |
31 | sub stop { |
32 | my $self = shift; |
33 | |
34 | $self->explode() if rand(1) > .5; |
35 | |
36 | $self->_stop(); |
37 | } |
38 | |
39 | sub start { |
40 | my $self = shift; |
41 | |
42 | $self->explode() if rand(1) > .5; |
43 | |
44 | $self->_start(); |
45 | } |
46 | |
47 | package Restartable::ButBroken; |
48 | use Moose::Role; |
49 | |
50 | with 'Restartable' => { excludes => [ 'stop', 'start' ] }; |
51 | |
52 | sub stop { |
53 | my $self = shift; |
54 | |
55 | $self->explode(); |
56 | } |
57 | |
58 | sub start { |
59 | my $self = shift; |
60 | |
61 | $self->explode(); |
62 | } |
63 | |
64 | =head1 DESCRIPTION |
65 | |
66 | Sometimes when you include a role in a class, you may want to leave |
67 | out some of its methods. In this example, we have a role C<Restartable> |
68 | which provides an C<is_paused> attribute, and two methods, C<stop> and |
69 | C<start>. The implementation of those two methods is irrelevant. |
70 | |
71 | Then we have two more roles which also implement the same interface, |
72 | each putting their own spin on the C<stop> and C<start> method. |
73 | |
74 | In the C<Restartable::ButUnreliable> role, we want to provide a new |
75 | implementation of C<stop> and C<start>, but still have access to the |
76 | original implementation. To do this, we alias the methods from |
77 | C<Restartable> to private methods, and provide wrappers around the |
78 | originals (1). |
79 | |
80 | In the C<Restartable::ButBroken> role, we want to provide an entirely |
81 | new behavior for C<stop> and C<start>, so we exclude them when |
82 | composing the C<Restartable> role into C<Restartable::ButBroken>. |
83 | |
84 | It's worth noting that the C<excludes> parameter also accepts a single |
85 | string as an argument if you just want to exclude one method. |
86 | |
87 | =head1 CONCLUSION |
88 | |
89 | Method exclusion and renaming can come in handy, especially when |
90 | building roles out of other roles. In this example, all of our roles |
546a7134 |
91 | implement the C<Restartable> role. Each role provides same API, but |
92 | each has a different implementation under the hood. |
2e3d0a0a |
93 | |
94 | You can also use the method aliasing and excluding features when |
95 | composing a role into a class. |
96 | |
97 | =head1 FOOTNOTES |
98 | |
99 | =over 4 |
100 | |
101 | =item (1) |
102 | |
103 | The mention of wrapper should tell you that we could do the same thing |
104 | using method modifiers, but for the sake of this example, we don't. |
105 | |
106 | =back |
107 | |
108 | =head1 AUTHOR |
109 | |
110 | Dave Rolsky E<lt>autarch@urth.orgE<gt> |
111 | |
112 | =head1 COPYRIGHT AND LICENSE |
113 | |
114 | Copyright 2006-2008 by Infinity Interactive, Inc. |
115 | |
116 | L<http://www.iinteractive.com> |
117 | |
118 | This library is free software; you can redistribute it and/or modify |
119 | it under the same terms as Perl itself. |
120 | |
121 | =cut |