Commit | Line | Data |
d5e84b86 |
1 | |
2 | =pod |
3 | |
5547fba7 |
4 | =begin testing-SETUP |
c79239a2 |
5 | |
6 | BEGIN { |
3d659f7f |
7 | eval 'use Test::Output;'; |
8 | if ($@) { |
9 | diag 'Test::Output is required for this test'; |
10 | ok(1); |
11 | exit 0; |
12 | } |
c79239a2 |
13 | } |
14 | |
5547fba7 |
15 | =end testing-SETUP |
c79239a2 |
16 | |
d5e84b86 |
17 | =head1 NAME |
18 | |
c8d5f1e1 |
19 | Moose::Cookbook::Extending::Recipe3 - Providing an alternate base object class |
d5e84b86 |
20 | |
21 | =head1 SYNOPSIS |
22 | |
23 | package MyApp::Base; |
24 | use Moose; |
25 | |
26 | extends 'Moose::Object'; |
27 | |
28 | before 'new' => sub { warn "Making a new " . $_[0] }; |
29 | |
30 | no Moose; |
31 | |
32 | package MyApp::UseMyBase; |
33 | use Moose (); |
554b7648 |
34 | use Moose::Exporter; |
d5e84b86 |
35 | |
aedcb7d9 |
36 | Moose::Exporter->setup_import_methods( also => 'Moose' ); |
d5e84b86 |
37 | |
554b7648 |
38 | sub init_meta { |
39 | shift; |
a8de959b |
40 | return Moose->init_meta( @_, base_class => 'MyApp::Base' ); |
d5e84b86 |
41 | } |
42 | |
43 | =head1 DESCRIPTION |
44 | |
9ac00c2b |
45 | A common extension is to provide an alternate base class. One way to |
46 | do that is to make a C<MyApp::base> and add C<S<extends |
47 | 'MyApp::Base'>> to every class in your application. That's pretty |
48 | tedious. Instead, you can create a Moose-alike module that sets the |
49 | base object class to C<MyApp::Base> for you. |
d5e84b86 |
50 | |
51 | Then, instead of writing C<S<use Moose>> you can write C<S<use |
52 | MyApp::UseMyBase>>. |
53 | |
54 | In this particular example, our base class issues some debugging |
9ac00c2b |
55 | output every time a new object is created, but you can think of some |
56 | more interesting things to do with your own base class. |
d5e84b86 |
57 | |
5a87a5ca |
58 | This uses the magic of L<Moose::Exporter>. When we call C<< |
59 | Moose::Exporter->setup_import_methods( also => 'Moose' ) >> it builds |
60 | C<import> and C<unimport> methods for you. The C<< also => 'Moose' >> |
61 | bit says that we want to export everything that Moose does. |
554b7648 |
62 | |
63 | The C<import> method that gets created will call our C<init_meta> |
5a87a5ca |
64 | method, passing it C<< for_caller => $caller >> as its |
9ac00c2b |
65 | arguments. The C<$caller> is set to the class that actually imported |
66 | us in the first place. |
554b7648 |
67 | |
68 | See the L<Moose::Exporter> docs for more details on its API. |
69 | |
70 | =head1 USING MyApp::UseMyBase |
71 | |
72 | To actually use our new base class, we simply use C<MyApp::UseMyBase> |
73 | I<instead> of C<Moose>. We get all the Moose sugar plus our new base |
74 | class. |
75 | |
76 | package Foo; |
77 | |
78 | use MyApp::UseMyBase; |
79 | |
80 | has 'size' => ( is => 'rw' ); |
81 | |
82 | no MyApp::UseMyBase; |
83 | |
9ac00c2b |
84 | =head1 CONCLUSION |
85 | |
86 | This is an awful lot of magic for a simple base class. You will often |
87 | want to combine a metaclass trait with a base class extension, and |
88 | that's when this technique is useful. |
89 | |
d5e84b86 |
90 | =head1 AUTHOR |
91 | |
92 | Dave Rolsky E<lt>autarch@urth.orgE<gt> |
93 | |
94 | =head1 COPYRIGHT AND LICENSE |
95 | |
7e0492d3 |
96 | Copyright 2006-2010 by Infinity Interactive, Inc. |
d5e84b86 |
97 | |
98 | L<http://www.iinteractive.com> |
99 | |
100 | This library is free software; you can redistribute it and/or modify |
101 | it under the same terms as Perl itself. |
102 | |
c79239a2 |
103 | =begin testing |
104 | |
105 | { |
106 | package Foo; |
107 | |
108 | MyApp::UseMyBase->import; |
109 | |
110 | has( 'size' => ( is => 'rw' ) ); |
111 | } |
112 | |
113 | ok( Foo->isa('MyApp::Base'), 'Foo isa MyApp::Base' ); |
114 | |
115 | ok( Foo->can('size'), 'Foo has a size method' ); |
116 | |
117 | my $foo; |
8b23f9f8 |
118 | stderr_like( |
c79239a2 |
119 | sub { $foo = Foo->new( size => 2 ) }, |
8b23f9f8 |
120 | qr/^Making a new Foo/, |
c79239a2 |
121 | 'got expected warning when calling Foo->new' |
122 | ); |
123 | |
124 | is( $foo->size(), 2, '$foo->size is 2' ); |
125 | |
126 | =end testing |
127 | |
d5e84b86 |
128 | =cut |