handle non-Moo superclass constructors
[gitmo/Moo.git] / lib / Moo.pm
1 package Moo;
2
3 use strictures 1;
4 use Moo::_Utils;
5
6 our $VERSION = '0.009003'; # 0.9.3
7 $VERSION = eval $VERSION;
8
9 our %MAKERS;
10
11 sub import {
12   my $target = caller;
13   my $class = shift;
14   strictures->import;
15   return if $MAKERS{$target}; # already exported into this package
16   *{_getglob("${target}::extends")} = sub {
17     _load_module($_) for @_;
18     # Can't do *{...} = \@_ or 5.10.0's mro.pm stops seeing @ISA
19     @{*{_getglob("${target}::ISA")}{ARRAY}} = @_;
20   };
21   *{_getglob("${target}::with")} = sub {
22     require Moo::Role;
23     die "Only one role supported at a time by with" if @_ > 1;
24     Moo::Role->apply_role_to_package($target, $_[0]);
25   };
26   $MAKERS{$target} = {};
27   *{_getglob("${target}::has")} = sub {
28     my ($name, %spec) = @_;
29     ($MAKERS{$target}{accessor} ||= do {
30       require Method::Generate::Accessor;
31       Method::Generate::Accessor->new
32     })->generate_method($target, $name, \%spec);
33     $class->_constructor_maker_for($target)
34           ->register_attribute_specs($name, \%spec);
35   };
36   foreach my $type (qw(before after around)) {
37     *{_getglob "${target}::${type}"} = sub {
38       require Class::Method::Modifiers;
39       _install_modifier($target, $type, @_);
40     };
41   }
42   {
43     no strict 'refs';
44     @{"${target}::ISA"} = do {
45       require Moo::Object; ('Moo::Object');
46     } unless @{"${target}::ISA"};
47   }
48 }
49
50 sub _constructor_maker_for {
51   my ($class, $target) = @_;
52   return unless $MAKERS{$target};
53   $MAKERS{$target}{constructor} ||= do {
54     require Method::Generate::Constructor;
55     my $con;
56
57     # using the -last- entry in @ISA means that classes created by
58     # Role::Tiny as N roles + superclass will still get the attributes
59     # from the superclass via the ->register_attribute_specs call later
60
61     if (my $super = do { no strict 'refs'; ${"${target}::ISA"}[-1] }) {
62       $con = $MAKERS{$super}{constructor} if $MAKERS{$super};
63     }
64     my $moo_constructor = !!$con || do {
65       my $t_new = $target->can('new');
66       $t_new and $t_new == Moo::Object->can('new');
67     };
68     require Moo::_mro unless $moo_constructor;
69     Method::Generate::Constructor
70       ->new(
71         package => $target,
72         accessor_generator => do {
73           require Method::Generate::Accessor;
74           Method::Generate::Accessor->new;
75         },
76         ($moo_constructor ? ()
77           : (construction_string => '$class->next::method(@_)'))
78       )
79       ->install_delayed
80       ->register_attribute_specs(%{$con?$con->all_attribute_specs:{}})
81   }
82 }
83
84 1;
85
86 =head1 NAME
87
88 Moo - Minimalist Object Orientation (with Moose compatiblity)
89
90 =head1 WARNING WARNING WARNING
91
92 This is a 0.9 release because we're fairly sure it works. For us. Until it's
93 tested in the wild, we make no guarantees it also works for you.
94
95 If this module does something unexpected, please submit a failing test.
96
97 But if it eats your cat, sleeps with your boyfriend, or pushes grandma down
98 the stairs to save her from the terrible secret of space, it's not our fault.
99
100 =head1 SYNOPSIS
101
102  package Cat::Food;
103
104  use Moo;
105  use Sub::Quote;
106
107  sub feed_lion {
108    my $self = shift;
109    my $amount = shift || 1;
110
111    $self->pounds( $self->pounds - $amount );
112  }
113
114  has taste => (
115    is => 'ro',
116  );
117
118  has brand => (
119    is  => 'ro',
120    isa => sub {
121      die "Only SWEET-TREATZ supported!" unless $_[0] eq 'SWEET-TREATZ'
122    },
123 );
124
125  has pounds => (
126    is  => 'rw',
127    isa => quote_sub q{ die "$_[0] is too much cat food!" unless $_[0] < 15 },
128  );
129
130  1;
131
132 and else where
133
134  my $full = Cat::Food->new(
135     taste  => 'DELICIOUS.',
136     brand  => 'SWEET-TREATZ',
137     pounds => 10,
138  );
139
140  $full->feed_lion;
141
142  say $full->pounds;
143
144 =head1 DESCRIPTION
145
146 This module is an extremely light-weight, high-performance L<Moose> replacement.
147 It also avoids depending on any XS modules to allow simple deployments.  The
148 name C<Moo> is based on the idea that it provides almost -but not quite- two
149 thirds of L<Moose>.
150
151 Unlike C<Mouse> this module does not aim at full L<Moose> compatibility.  See
152 L</INCOMPATIBILITIES> for more details.
153
154 =head1 WHY MOO EXISTS
155
156 If you want a full object system with a rich Metaprotocol, L<Moose> is
157 already wonderful.
158
159 I've tried several times to use L<Mouse> but it's 3x the size of Moo and
160 takes longer to load than most of my Moo based CGI scripts take to run.
161
162 If you don't want L<Moose>, you don't want "less metaprotocol" like L<Mouse>,
163 you want "as little as possible" - which means "no metaprotocol", which is
164 what Moo provides.
165
166 By Moo 1.0 I intend to have Moo's equivalent of L<Any::Moose> built in -
167 if Moose gets loaded, any Moo class or role will act as a Moose equivalent
168 if treated as such.
169
170 Hence - Moo exists as its name - Minimal Object Orientation - with a pledge
171 to make it smooth to upgrade to L<Moose> when you need more than minimal
172 features.
173
174 =head1 IMPORTED METHODS
175
176 =head2 new
177
178  Foo::Bar->new( attr1 => 3 );
179
180 or
181
182  Foo::Bar->new({ attr1 => 3 });
183
184 =head2 BUILDARGS
185
186 This feature from Moose is not yet supported.
187
188 =head2 BUILDALL
189
190 Don't override (or probably even call) this method.  Instead, you can define
191 a C<BUILD> method on your class and the constructor will automatically call the
192 C<BUILD> method from parent down to child after the object has been
193 instantiated.  Typically this is used for object validation or possibly logging.
194
195 =head2 does
196
197  if ($foo->does('Some::Role1')) {
198    ...
199  }
200
201 Returns true if the object composes in the passed role.
202
203 =head1 IMPORTED SUBROUTINES
204
205 =head2 extends
206
207  extends 'Parent::Class';
208
209 Declares base class. Multiple superclasses can be passed for multiple
210 inheritance (but please use roles instead).
211
212 Calling extends more than once will REPLACE your superclasses, not add to
213 them like 'use base' would.
214
215 =head2 with
216
217  with 'Some::Role1';
218  with 'Some::Role2';
219
220 Composes a L<Role::Tiny> into current class.  Only one role may be composed in
221 at a time to allow the code to remain as simple as possible.
222
223 =head2 has
224
225  has attr => (
226    is => 'ro',
227  );
228
229 Declares an attribute for the class.
230
231 The options for C<has> are as follows:
232
233 =over 2
234
235 =item * is
236
237 B<required>, must be C<ro> or C<rw>.  Unsurprisingly, C<ro> generates an
238 accessor that will not respond to arguments; to be clear: a getter only. C<rw>
239 will create a perlish getter/setter.
240
241 =item * isa
242
243 Takes a coderef which is meant to validate the attribute.  Unlike L<Moose> Moo
244 does not include a basic type system, so instead of doing C<< isa => 'Num' >>,
245 one should do
246
247  isa => quote_sub q{
248    die "$_[0] is not a number!" unless looks_like_number $_[0]
249  },
250
251 L<Sub::Quote aware|/SUB QUOTE AWARE>
252
253 =item * coerce
254
255 This Moose feature is not yet supported
256
257 =begin hide
258
259 Takes a coderef which is meant to coerce the attribute.  The basic idea is to
260 do something like the following:
261
262  coerce => quote_sub q{
263    $_[0] + 1 unless $_[0] % 2
264  },
265
266 L<Sub::Quote aware|/SUB QUOTE AWARE>
267
268 =end hide
269
270 =item * trigger
271
272 Takes a coderef which will get called any time the attribute is set. Coderef
273 will be invoked against the object with the new value as an argument.
274
275 Note that Moose also passes the old value, if any; this feature is not yet
276 supported.
277
278 L<Sub::Quote aware|/SUB QUOTE AWARE>
279
280 =item * default
281
282 Takes a coderef which will get called with $self as its only argument
283 to populate an attribute if no value is supplied to the constructor - or
284 if the attribute is lazy, when the attribute is first retrieved if no
285 value has yet been provided.
286
287 Note that if your default is fired during new() there is no guarantee that
288 other attributes have been populated yet so you should not rely on their
289 existence.
290
291 L<Sub::Quote aware|/SUB QUOTE AWARE>
292
293 =item * predicate
294
295 Takes a method name which will return true if an attribute has a value.
296
297 A common example of this would be to call it C<has_$foo>, implying that the
298 object has a C<$foo> set.
299
300 =item * builder
301
302 Takes a method name which will be called to create the attribute - functions
303 exactly like default except that instead of calling
304
305   $default->($self);
306
307 Moo will call
308
309   $self->$builder;
310
311 =item * clearer
312
313 Takes a method name which will clear the attribute.
314
315 =item * lazy
316
317 B<Boolean>.  Set this if you want values for the attribute to be grabbed
318 lazily.  This is usually a good idea if you have a L</builder> which requires
319 another attribute to be set.
320
321 =item * required
322
323 B<Boolean>.  Set this if the attribute must be passed on instantiation.
324
325 =item * weak_ref
326
327 B<Boolean>.  Set this if you want the reference that the attribute contains to
328 be weakened; use this when circular references are possible, which will cause
329 leaks.
330
331 =item * init_arg
332
333 Takes the name of the key to look for at instantiation time of the object.  A
334 common use of this is to make an underscored attribute have a non-underscored
335 initialization name. C<undef> means that passing the value in on instantiation
336
337 =back
338
339 =head2 before
340
341  before foo => sub { ... };
342
343 See L<< Class::Method::Modifiers/before method(s) => sub { ... } >> for full
344 documentation.
345
346 =head2 around
347
348  around foo => sub { ... };
349
350 See L<< Class::Method::Modifiers/around method(s) => sub { ... } >> for full
351 documentation.
352
353 =head2 after
354
355  after foo => sub { ... };
356
357 See L<< Class::Method::Modifiers/after method(s) => sub { ... } >> for full
358 documentation.
359
360 =head1 SUB QUOTE AWARE
361
362 L<Sub::Quote/quote_sub> allows us to create coderefs that are "inlineable,"
363 giving us a handy, XS-free speed boost.  Any option that is L<Sub::Quote>
364 aware can take advantage of this.
365
366 =head1 INCOMPATIBILITIES WITH MOOSE
367
368 You can only compose one role at a time.  If your application is large or
369 complex enough to warrant complex composition, you wanted L<Moose>.
370
371 There is no complex type system.  C<isa> is verified with a coderef, if you
372 need complex types, just make a library of coderefs, or better yet, functions
373 that return quoted subs.
374
375 C<initializer> is not supported in core since the author considers it to be a
376 bad idea but may be supported by an extension in future.
377
378 There is no meta object.  If you need this level of complexity you wanted
379 L<Moose> - Moo succeeds at being small because it explicitly does not
380 provide a metaprotocol.
381
382 No support for C<super>, C<override>, C<inner>, or C<augment> - override can
383 be handled by around albeit with a little more typing, and the author considers
384 augment to be a bad idea.
385
386 L</default> only supports coderefs, because doing otherwise is usually a
387 mistake anyway.
388
389 C<lazy_build> is not supported per se, but of course it will work if you
390 manually set all the options it implies.
391
392 C<auto_deref> is not supported since the author considers it a bad idea.
393
394 C<documentation> is not supported since it's a very poor replacement for POD.