make github the primary repository
[gitmo/Moose.git] / lib / Moose / Cookbook / Legacy / Debugging_BaseClassReplacement.pm
CommitLineData
cb235596 1package Moose::Cookbook::Legacy::Debugging_BaseClassReplacement;
2
3# ABSTRACT: Providing an alternate base object class
4
5
6
7=pod
8
9=head1 NAME
10
11Moose::Cookbook::Extending::Recipe3 - Providing an alternate base object class
12
13=head1 VERSION
14
15version 2.0402
16
17=head1 SYNOPSIS
18
19 package MyApp::Base;
20 use Moose;
21
22 extends 'Moose::Object';
23
24 before 'new' => sub { warn "Making a new " . $_[0] };
25
26 no Moose;
27
28 package MyApp::UseMyBase;
29 use Moose ();
30 use Moose::Exporter;
31
32 Moose::Exporter->setup_import_methods( also => 'Moose' );
33
34 sub init_meta {
35 shift;
36 return Moose->init_meta( @_, base_class => 'MyApp::Base' );
37 }
38
39=head1 DESCRIPTION
40
41B<WARNING: Replacing the base class entirely, as opposed to applying roles to
42the base class, is strongly discouraged. This recipe is provided solely for
43reference when encountering older code that does this.>
44
45A common extension is to provide an alternate base class. One way to
46do 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
48tedious. Instead, you can create a Moose-alike module that sets the
49base object class to C<MyApp::Base> for you.
50
51Then, instead of writing C<S<use Moose>> you can write C<S<use
52MyApp::UseMyBase>>.
53
54In this particular example, our base class issues some debugging
55output every time a new object is created, but you can think of some
56more interesting things to do with your own base class.
57
58This uses the magic of L<Moose::Exporter>. When we call C<<
59Moose::Exporter->setup_import_methods( also => 'Moose' ) >> it builds
60C<import> and C<unimport> methods for you. The C<< also => 'Moose' >>
61bit says that we want to export everything that Moose does.
62
63The C<import> method that gets created will call our C<init_meta>
64method, passing it C<< for_caller => $caller >> as its
65arguments. The C<$caller> is set to the class that actually imported
66us in the first place.
67
68See the L<Moose::Exporter> docs for more details on its API.
69
70=for testing-SETUP use Test::Requires {
71 'Test::Output' => '0',
72};
73
74=head1 USING MyApp::UseMyBase
75
76To actually use our new base class, we simply use C<MyApp::UseMyBase>
77I<instead> of C<Moose>. We get all the Moose sugar plus our new base
78class.
79
80 package Foo;
81
82 use MyApp::UseMyBase;
83
84 has 'size' => ( is => 'rw' );
85
86 no MyApp::UseMyBase;
87
88=head1 CONCLUSION
89
90This is an awful lot of magic for a simple base class. You will often
91want to combine a metaclass trait with a base class extension, and
92that's when this technique is useful.
93
94=begin testing
95
96{
97 package Foo;
98
99 MyApp::UseMyBase->import;
100
101 has( 'size' => ( is => 'rw' ) );
102}
103
104ok( Foo->isa('MyApp::Base'), 'Foo isa MyApp::Base' );
105
106ok( Foo->can('size'), 'Foo has a size method' );
107
108my $foo;
109stderr_like(
110 sub { $foo = Foo->new( size => 2 ) },
111 qr/^Making a new Foo/,
112 'got expected warning when calling Foo->new'
113);
114
115is( $foo->size(), 2, '$foo->size is 2' );
116
117=end testing
118
119=head1 AUTHOR
120
121Moose is maintained by the Moose Cabal, along with the help of many contributors. See L<Moose/CABAL> and L<Moose/CONTRIBUTORS> for details.
122
123=head1 COPYRIGHT AND LICENSE
124
125This software is copyright (c) 2012 by Infinity Interactive, Inc..
126
127This is free software; you can redistribute it and/or modify it under
128the same terms as the Perl 5 programming language system itself.
129
130=cut
131
132
133__END__
134