Moved recipes to get rid of Basic 8 as a TODO, and just let them be numbered sequenti...
[gitmo/Moose.git] / lib / Moose / Cookbook / Basics / Recipe11.pod
CommitLineData
04d80e2a 1
2=pod
3
1f476b5f 4=begin testing-SETUP
5
6BEGIN {
7 eval 'use DateTime; use DateTime::Calendar::Mayan;';
8 if ($@) {
9 diag 'DateTime & DateTime::Calendar::Mayan required for this test';
10 ok(1);
11 exit 0;
12 }
13}
14
15=end testing-SETUP
16
04d80e2a 17=head1 NAME
18
1f476b5f 19Moose::Cookbook::Basics::Recipe12 - Extending a non-Moose base class
04d80e2a 20
21=head1 SYNOPSIS
22
1f476b5f 23 package My::DateTime;
04d80e2a 24
1f476b5f 25 use Moose;
26 extends qw( DateTime Moose::Object );
04d80e2a 27
1f476b5f 28 use DateTime::Calendar::Mayan;
04d80e2a 29
1f476b5f 30 has 'mayan_date' => (
31 is => 'ro',
32 isa => 'DateTime::Calendar::Mayan',
33 init_arg => undef,
34 lazy => 1,
35 builder => '_build_mayan_date',
36 clearer => '_clear_mayan_date',
37 predicate => 'has_mayan_date',
04d80e2a 38 );
39
1f476b5f 40 sub new {
04d80e2a 41 my $class = shift;
42
1f476b5f 43 my $obj = $class->SUPER::new(@_);
44
45 return $class->meta->new_object(
46 __INSTANCE__ => $obj,
47 @_,
48 );
04d80e2a 49 }
50
1f476b5f 51 after 'set' => sub {
52 $_[0]->_clear_mayan_date;
53 };
04d80e2a 54
1f476b5f 55 sub _build_mayan_date {
56 DateTime::Calendar::Mayan->from_object( object => $_[0] );
04d80e2a 57 }
58
59=head1 DESCRIPTION
60
1f476b5f 61This recipe demonstrates how to use Moose to subclass a parent which
62is not Moose based. This recipe only works if the parent class uses a
63blessed hash reference for object instances. If your parent is doing
64something funkier, you should check out L<MooseX::InsideOut>.
04d80e2a 65
1f476b5f 66You might also want to check out L<MooseX::NonMoose>, which does all
67the grunt work for you.
04d80e2a 68
1f476b5f 69There are a couple pieces worth noting:
04d80e2a 70
1f476b5f 71 use Moose;
72 extends qw( DateTime Moose::Object );
04d80e2a 73
1f476b5f 74First, we C<use Moose> just like we always do. This lets us declare
75attributes and use all the Moose sugar to which we are accustomed.
04d80e2a 76
1f476b5f 77The C<extends> declaration explicitly include L<Moose::Object> as well
78as L<DateTime>. This lets us use methods which are provided by
79L<Moose::Object>, like C<does>.
04d80e2a 80
1f476b5f 81The constructor demonstrates a particular hack/pattern (hacktern?) for
82working with non-Moose parent classes:
04d80e2a 83
1f476b5f 84 sub new {
85 my $class = shift;
04d80e2a 86
1f476b5f 87 my $obj = $class->SUPER::new(@_);
04d80e2a 88
1f476b5f 89 return $class->meta->new_object(
90 __INSTANCE__ => $obj,
91 @_,
92 );
93 }
04d80e2a 94
1f476b5f 95We explicitly call C<< $class->meta->new_object >> and pass the
96already-created object in the C<__INSTANCE__> key. Internally, Moose
97will take the existing object and initialize any attributes defined in
98our subclass.
04d80e2a 99
1f476b5f 100The C<after> modifier works just like we'd expect. The fact that
101C<set> is defined in our non-Moose parent does not matter.
04d80e2a 102
103=head1 CONCLUSION
104
1f476b5f 105Moose can play nice with non-Moose classes when you follow the pattern
106shown here. Your subclass has access to all the power of Moose,
107including attribute declaration, method modifiers, type constraints
108(for new attributes), and roles.
04d80e2a 109
1f476b5f 110However, you won't be able to easily override a parent's "attributes",
111since they're not Moose attributes. Nor will you be able to inline a
112constructor, since you need to explicitly use the metaclass's object
113constructor.
04d80e2a 114
115=head1 AUTHOR
116
117Dave Rolsky E<lt>autarch@urth.orgE<gt>
118
119=head1 COPYRIGHT AND LICENSE
120
1f476b5f 121Copyright 2009 by Infinity Interactive, Inc.
04d80e2a 122
123L<http://www.iinteractive.com>
124
125This library is free software; you can redistribute it and/or modify
126it under the same terms as Perl itself.
127
1f476b5f 128=begin testing
129
130my $dt = My::DateTime->new( year => 1970, month => 2, day => 24 );
131
132can_ok( $dt, 'mayan_date' );
133isa_ok( $dt->mayan_date, 'DateTime::Calendar::Mayan' );
134is( $dt->mayan_date->date, '12.17.16.9.19', 'got expected mayan date' );
135
136$dt->set( year => 2009 );
137ok( ! $dt->has_mayan_date, 'mayan_date is cleared after call to ->set' );
138
139=end testing
140
04d80e2a 141=cut