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