Commit | Line | Data |
04d80e2a |
1 | |
2 | =pod |
3 | |
1f476b5f |
4 | =begin testing-SETUP |
5 | |
6 | BEGIN { |
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 | |
31098197 |
19 | Moose::Cookbook::Basics::Recipe11 - 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 |
61 | This recipe demonstrates how to use Moose to subclass a parent which |
62 | is not Moose based. This recipe only works if the parent class uses a |
63 | blessed hash reference for object instances. If your parent is doing |
64 | something funkier, you should check out L<MooseX::InsideOut>. |
04d80e2a |
65 | |
1f476b5f |
66 | You might also want to check out L<MooseX::NonMoose>, which does all |
67 | the grunt work for you. |
04d80e2a |
68 | |
1f476b5f |
69 | There are a couple pieces worth noting: |
04d80e2a |
70 | |
1f476b5f |
71 | use Moose; |
72 | extends qw( DateTime Moose::Object ); |
04d80e2a |
73 | |
1f476b5f |
74 | First, we C<use Moose> just like we always do. This lets us declare |
75 | attributes and use all the Moose sugar to which we are accustomed. |
04d80e2a |
76 | |
1f476b5f |
77 | The C<extends> declaration explicitly include L<Moose::Object> as well |
78 | as L<DateTime>. This lets us use methods which are provided by |
79 | L<Moose::Object>, like C<does>. |
04d80e2a |
80 | |
1f476b5f |
81 | The constructor demonstrates a particular hack/pattern (hacktern?) for |
82 | working 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 |
95 | We explicitly call C<< $class->meta->new_object >> and pass the |
96 | already-created object in the C<__INSTANCE__> key. Internally, Moose |
97 | will take the existing object and initialize any attributes defined in |
98 | our subclass. |
04d80e2a |
99 | |
1f476b5f |
100 | The C<after> modifier works just like we'd expect. The fact that |
101 | C<set> is defined in our non-Moose parent does not matter. |
04d80e2a |
102 | |
103 | =head1 CONCLUSION |
104 | |
1f476b5f |
105 | Moose can play nice with non-Moose classes when you follow the pattern |
106 | shown here. Your subclass has access to all the power of Moose, |
107 | including attribute declaration, method modifiers, type constraints |
108 | (for new attributes), and roles. |
04d80e2a |
109 | |
1f476b5f |
110 | However, you won't be able to easily override a parent's "attributes", |
111 | since they're not Moose attributes. Nor will you be able to inline a |
112 | constructor, since you need to explicitly use the metaclass's object |
113 | constructor. |
04d80e2a |
114 | |
115 | =head1 AUTHOR |
116 | |
117 | Dave Rolsky E<lt>autarch@urth.orgE<gt> |
118 | |
119 | =head1 COPYRIGHT AND LICENSE |
120 | |
1f476b5f |
121 | Copyright 2009 by Infinity Interactive, Inc. |
04d80e2a |
122 | |
123 | L<http://www.iinteractive.com> |
124 | |
125 | This library is free software; you can redistribute it and/or modify |
126 | it under the same terms as Perl itself. |
127 | |
1f476b5f |
128 | =begin testing |
129 | |
130 | my $dt = My::DateTime->new( year => 1970, month => 2, day => 24 ); |
131 | |
132 | can_ok( $dt, 'mayan_date' ); |
133 | isa_ok( $dt->mayan_date, 'DateTime::Calendar::Mayan' ); |
134 | is( $dt->mayan_date->date, '12.17.16.9.19', 'got expected mayan date' ); |
135 | |
136 | $dt->set( year => 2009 ); |
137 | ok( ! $dt->has_mayan_date, 'mayan_date is cleared after call to ->set' ); |
138 | |
139 | =end testing |
140 | |
04d80e2a |
141 | =cut |