Add one more deleted recipe to the Legacy section
[gitmo/Moose.git] / lib / Moose / Cookbook / Legacy / Debugging_BaseClassReplacement.pm
1 package Moose::Cookbook::Legacy::Debugging_BaseClassReplacement;
2
3 # ABSTRACT: Providing an alternate base object class
4
5
6
7 =pod
8
9 =head1 NAME
10
11 Moose::Cookbook::Extending::Recipe3 - Providing an alternate base object class
12
13 =head1 VERSION
14
15 version 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
41 B<WARNING: Replacing the base class entirely, as opposed to applying roles to
42 the base class, is strongly discouraged. This recipe is provided solely for
43 reference when encountering older code that does this.>
44
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.
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
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.
57
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.
62
63 The C<import> method that gets created will call our C<init_meta>
64 method, passing it C<< for_caller => $caller >> as its
65 arguments. The C<$caller> is set to the class that actually imported
66 us in the first place.
67
68 See 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
76 To actually use our new base class, we simply use C<MyApp::UseMyBase>
77 I<instead> of C<Moose>. We get all the Moose sugar plus our new base
78 class.
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
90 This is an awful lot of magic for a simple base class. You will often
91 want to combine a metaclass trait with a base class extension, and
92 that'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
104 ok( Foo->isa('MyApp::Base'), 'Foo isa MyApp::Base' );
105
106 ok( Foo->can('size'), 'Foo has a size method' );
107
108 my $foo;
109 stderr_like(
110     sub { $foo = Foo->new( size => 2 ) },
111     qr/^Making a new Foo/,
112     'got expected warning when calling Foo->new'
113 );
114
115 is( $foo->size(), 2, '$foo->size is 2' );
116
117 =end testing
118
119 =head1 AUTHOR
120
121 Moose 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
125 This software is copyright (c) 2012 by Infinity Interactive, Inc..
126
127 This is free software; you can redistribute it and/or modify it under
128 the same terms as the Perl 5 programming language system itself.
129
130 =cut
131
132
133 __END__
134