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