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