6 Moose::Cookbook::Basics::Recipe6 - The augment/inner example
10 package Document::Page;
13 has 'body' => ( is => 'rw', isa => 'Str', default => sub {''} );
23 my ( $self, $appendage ) = @_;
24 $self->body( $self->body . $appendage );
27 sub open_page { (shift)->append_body('<page>') }
28 sub close_page { (shift)->append_body('</page>') }
30 package Document::PageWithHeadersAndFooters;
33 extends 'Document::Page';
35 augment 'create' => sub {
42 sub create_header { (shift)->append_body('<header/>') }
43 sub create_footer { (shift)->append_body('<footer/>') }
48 extends 'Document::PageWithHeadersAndFooters';
50 augment 'create' => sub {
52 $self->create_tps_report;
56 sub create_tps_report {
57 (shift)->append_body('<report type="tps"/>');
60 # <page><header/><report type="tps"/><footer/></page>
61 my $report_xml = TPSReport->new->create;
65 This recipe shows how the C<augment> method modifier works. This
66 modifier reverses the normal subclass to parent method resolution
67 order. With an C<augment> modifier the I<least> specific method is
68 called first. Each successive call to C<inner> descends the
69 inheritance tree, ending at the most specific subclass.
71 The C<augment> modifier lets you design a parent class that can be
72 extended in a specific way. The parent provides generic wrapper
73 functionality, and the subclasses fill in the details.
75 In the example above, we've created a set of document classes, with
76 the most specific being the C<TPSReport> class.
78 We start with the least specific class, C<Document::Page>. Its create
79 method contains a call to C<inner()>:
88 The C<inner> function is exported by C<Moose>, and is like C<super>
89 for augmented methods. When C<inner> is called, Moose finds the next
90 method in the chain, which is the C<augment> modifier in
91 C<Document::PageWithHeadersAndFooters>. You'll note that we can call
92 C<inner> in our modifier:
94 augment 'create' => sub {
101 This finds the next most specific modifier, in the C<TPSReport> class.
103 Finally, in the C<TPSReport> class, the chain comes to an end:
105 augment 'create' => sub {
107 $self->create_tps_report;
111 We do call the C<inner> function one more time, but since there is no
112 more specific subclass, this is a no-op. Making this call means we can
113 easily subclass C<TPSReport> in the future.
117 The C<augment> modifier is a powerful tool for creating a set of
118 nested wrappers. It's not something you will need often, but when you
119 do, it is very handy.
123 Stevan Little E<lt>stevan@iinteractive.comE<gt>
125 Dave Rolsky E<lt>autarch@urth.orgE<gt>
127 =head1 COPYRIGHT AND LICENSE
129 Copyright 2007-2009 by Infinity Interactive, Inc.
131 L<http://www.iinteractive.com>
133 This library is free software; you can redistribute it and/or modify
134 it under the same terms as Perl itself.
138 my $tps_report = TPSReport->new;
139 isa_ok( $tps_report, 'TPSReport' );
143 q{<page><header/><report type="tps"/><footer/></page>},
144 '... got the right TPS report'