foo
[gitmo/Moose.git] / lib / Moose.pm
CommitLineData
fcd84ca9 1
2package Moose;
3
4use strict;
5use warnings;
6
2d562421 7our $VERSION = '0.05';
fcd84ca9 8
cc65ead0 9use Scalar::Util 'blessed', 'reftype';
fcd84ca9 10use Carp 'confess';
bc1e29b5 11use Sub::Name 'subname';
fcd84ca9 12
7f18097c 13use UNIVERSAL::require;
2d562421 14use Sub::Exporter;
7f18097c 15
ef1d5f4b 16use Class::MOP;
17
c0e30cf5 18use Moose::Meta::Class;
7415b2cb 19use Moose::Meta::TypeConstraint;
7c13858b 20use Moose::Meta::TypeCoercion;
78cd1d3b 21use Moose::Meta::Attribute;
ddd0ec20 22use Moose::Meta::Instance;
c0e30cf5 23
fcd84ca9 24use Moose::Object;
7415b2cb 25use Moose::Util::TypeConstraints;
a15dff8d 26
a3c7e2fe 27{
28 my ( $CALLER, %METAS );
29
2d562421 30 sub _find_meta {
a3c7e2fe 31 my $class = $CALLER;
32
33 return $METAS{$class} if exists $METAS{$class};
34
35 # make a subtype for each Moose class
36 subtype $class
37 => as 'Object'
38 => where { $_->isa($class) }
39 unless find_type_constraint($class);
40
41 my $meta;
42 if ($class->can('meta')) {
fcec2383 43 # NOTE:
44 # this is the case where the metaclass pragma
45 # was used before the 'use Moose' statement to
46 # override a specific class
a3c7e2fe 47 $meta = $class->meta();
48 (blessed($meta) && $meta->isa('Moose::Meta::Class'))
49 || confess "Whoops, not møøsey enough";
50 }
51 else {
fcec2383 52 # NOTE:
53 # this is broken currently, we actually need
54 # to allow the possiblity of an inherited
55 # meta, which will not be visible until the
56 # user 'extends' first. This needs to have
57 # more intelligence to it
590868a3 58 $meta = Moose::Meta::Class->initialize($class);
a3c7e2fe 59 $meta->add_method('meta' => sub {
60 # re-initialize so it inherits properly
fcb7afc2 61 Moose::Meta::Class->initialize(blessed($_[0]) || $_[0]);
a3c7e2fe 62 })
63 }
64
65 # make sure they inherit from Moose::Object
66 $meta->superclasses('Moose::Object')
67 unless $meta->superclasses();
68
69 return $METAS{$class} = $meta;
70 }
71
72 my %exports = (
73 extends => sub {
2d562421 74 my $meta = _find_meta();
3d544ed5 75 return subname 'Moose::extends' => sub {
a3c7e2fe 76 _load_all_classes(@_);
77 $meta->superclasses(@_)
78 };
79 },
80 with => sub {
2d562421 81 my $meta = _find_meta();
3d544ed5 82 return subname 'Moose::with' => sub {
a3c7e2fe 83 my ($role) = @_;
84 _load_all_classes($role);
85 $role->meta->apply($meta);
86 };
87 },
88 has => sub {
2d562421 89 my $meta = _find_meta();
3d544ed5 90 return subname 'Moose::has' => sub {
a3c7e2fe 91 my ($name, %options) = @_;
2d2b92e5 92 if ($name =~ /^\+(.*)/) {
1d768fb1 93 my $inherited_attr = $meta->find_attribute_by_name($1);
94 (defined $inherited_attr)
95 || confess "Could not find an attribute by the name of '$1' to inherit from";
ce0e8d63 96 my $new_attr = $inherited_attr->clone_and_inherit_options(%options);
1d768fb1 97 $meta->add_attribute($new_attr);
b0ea39ef 98 }
99 else {
2d2b92e5 100 if ($options{metaclass}) {
101 _load_all_classes($options{metaclass});
102 $meta->add_attribute($options{metaclass}->new($name, %options));
103 }
104 else {
105 $meta->add_attribute($name, %options);
106 }
b0ea39ef 107 }
a3c7e2fe 108 };
109 },
110 before => sub {
2d562421 111 my $meta = _find_meta();
3d544ed5 112 return subname 'Moose::before' => sub {
a3c7e2fe 113 my $code = pop @_;
114 $meta->add_before_method_modifier($_, $code) for @_;
115 };
116 },
117 after => sub {
2d562421 118 my $meta = _find_meta();
3d544ed5 119 return subname 'Moose::after' => sub {
a3c7e2fe 120 my $code = pop @_;
121 $meta->add_after_method_modifier($_, $code) for @_;
122 };
123 },
124 around => sub {
2d562421 125 my $meta = _find_meta();
3d544ed5 126 return subname 'Moose::around' => sub {
a3c7e2fe 127 my $code = pop @_;
128 $meta->add_around_method_modifier($_, $code) for @_;
129 };
130 },
131 super => sub {
2d562421 132 my $meta = _find_meta();
3d544ed5 133 return subname 'Moose::super' => sub {};
a3c7e2fe 134 },
135 override => sub {
2d562421 136 my $meta = _find_meta();
3d544ed5 137 return subname 'Moose::override' => sub {
a3c7e2fe 138 my ($name, $method) = @_;
139 $meta->add_override_method_modifier($name => $method);
140 };
141 },
142 inner => sub {
2d562421 143 my $meta = _find_meta();
3d544ed5 144 return subname 'Moose::inner' => sub {};
a3c7e2fe 145 },
146 augment => sub {
2d562421 147 my $meta = _find_meta();
3d544ed5 148 return subname 'Moose::augment' => sub {
a3c7e2fe 149 my ($name, $method) = @_;
150 $meta->add_augment_method_modifier($name => $method);
151 };
152 },
153 confess => sub {
154 return \&Carp::confess;
155 },
156 blessed => sub {
157 return \&Scalar::Util::blessed;
54b1cdf0 158 },
159 all_methods => sub {
065b95d5 160 subname 'Moose::all_methods' => sub () {
54b1cdf0 161 sub {
162 my ( $class, $delegate_class ) = @_;
163 $delegate_class->compute_all_applicable_methods();
164 }
165 }
a3c7e2fe 166 }
167 );
3d544ed5 168
a3c7e2fe 169 my $exporter = Sub::Exporter::build_exporter({
170 exports => \%exports,
171 groups => {
172 default => [':all']
173 }
174 });
175
fcb7afc2 176 sub import {
a3c7e2fe 177 $CALLER = caller();
178
179 # we should never export to main
180 return if $CALLER eq 'main';
181
182 goto $exporter;
fcb7afc2 183 }
fcd84ca9 184}
185
e9bb8a31 186## Utility functions
187
78cd1d3b 188sub _load_all_classes {
e9bb8a31 189 foreach my $super (@_) {
190 # see if this is already
191 # loaded in the symbol table
192 next if _is_class_already_loaded($super);
193 # otherwise require it ...
194 ($super->require)
195 || confess "Could not load superclass '$super' because : " . $UNIVERSAL::require::ERROR;
196 }
197}
198
d7f17ebb 199sub _is_class_already_loaded {
200 my $name = shift;
201 no strict 'refs';
202 return 1 if defined ${"${name}::VERSION"} || defined @{"${name}::ISA"};
203 foreach (keys %{"${name}::"}) {
204 next if substr($_, -2, 2) eq '::';
205 return 1 if defined &{"${name}::$_"};
206 }
207 return 0;
208}
209
fcd84ca9 2101;
211
212__END__
213
214=pod
215
216=head1 NAME
217
e522431d 218Moose - Moose, it's the new Camel
fcd84ca9 219
220=head1 SYNOPSIS
e522431d 221
222 package Point;
223 use Moose;
224
182134e8 225 has 'x' => (isa => 'Int', is => 'rw');
226 has 'y' => (isa => 'Int', is => 'rw');
e522431d 227
228 sub clear {
229 my $self = shift;
230 $self->x(0);
231 $self->y(0);
232 }
233
234 package Point3D;
235 use Moose;
236
237 extends 'Point';
09fdc1dc 238
182134e8 239 has 'z' => (isa => 'Int');
e522431d 240
241 after 'clear' => sub {
242 my $self = shift;
243 $self->{z} = 0;
244 };
245
246=head1 CAVEAT
247
79592a54 248This is an early release of this module, it still needs
e522431d 249some fine tuning and B<lots> more documentation. I am adopting
250the I<release early and release often> approach with this module,
251so keep an eye on your favorite CPAN mirror!
252
fcd84ca9 253=head1 DESCRIPTION
254
e522431d 255Moose is an extension of the Perl 5 object system.
256
257=head2 Another object system!?!?
fcd84ca9 258
e522431d 259Yes, I know there has been an explosion recently of new ways to
260build object's in Perl 5, most of them based on inside-out objects,
261and other such things. Moose is different because it is not a new
262object system for Perl 5, but instead an extension of the existing
263object system.
3c7278fb 264
e522431d 265Moose is built on top of L<Class::MOP>, which is a metaclass system
266for Perl 5. This means that Moose not only makes building normal
505c6fac 267Perl 5 objects better, but it also provides the power of metaclass
268programming.
e522431d 269
270=head2 What does Moose stand for??
271
272Moose doesn't stand for one thing in particular, however, if you
273want, here are a few of my favorites, feel free to contribute
274more :)
275
276=over 4
277
5569c072 278=item Make Other Object Systems Envious
e522431d 279
280=item Makes Object Orientation So Easy
281
5569c072 282=item Makes Object Orientation Spiffy- Er (sorry ingy)
505c6fac 283
5569c072 284=item Most Other Object Systems Emasculate
505c6fac 285
286=item My Overcraft Overfilled (with) Some Eels
287
288=item Moose Often Ovulate Sorta Early
289
505c6fac 290=item Many Overloaded Object Systems Exists
291
292=item Moose Offers Often Super Extensions
293
446e850f 294=item Meta Object Orientation Syntax Extensions
295
e522431d 296=back
3c7278fb 297
6ba6d68c 298=head1 BUILDING CLASSES WITH MOOSE
299
300Moose makes every attempt to provide as much convience during class
301construction/definition, but still stay out of your way if you want
302it to. Here are some of the features Moose provides:
303
304Unless specified with C<extends>, any class which uses Moose will
305inherit from L<Moose::Object>.
306
307Moose will also manage all attributes (including inherited ones) that
308are defined with C<has>. And assuming that you call C<new> which is
309inherited from L<Moose::Object>, then this includes properly initializing
310all instance slots, setting defaults where approprtiate and performing any
311type constraint checking or coercion.
312
79592a54 313For more details, see the ever expanding L<Moose::Cookbook>.
314
6ba6d68c 315=head1 EXPORTED FUNCTIONS
316
317Moose will export a number of functions into the class's namespace, which
318can then be used to set up the class. These functions all work directly
319on the current class.
320
321=over 4
322
323=item B<meta>
324
325This is a method which provides access to the current class's metaclass.
326
327=item B<extends (@superclasses)>
328
329This function will set the superclass(es) for the current class.
330
331This approach is recommended instead of C<use base>, because C<use base>
332actually C<push>es onto the class's C<@ISA>, whereas C<extends> will
333replace it. This is important to ensure that classes which do not have
334superclasses properly inherit from L<Moose::Object>.
335
e9ec68d6 336=item B<with ($role)>
337
76d37e5a 338This will apply a given C<$role> to the local class. Role support is
339currently very experimental, see L<Moose::Role> for more details.
e9ec68d6 340
6ba6d68c 341=item B<has ($name, %options)>
342
343This will install an attribute of a given C<$name> into the current class.
344The list of C<%options> are the same as those provided by both
345L<Class::MOP::Attribute> and L<Moose::Meta::Attribute>, in addition to a
346few convience ones provided by Moose which are listed below:
347
348=over 4
349
076c81ed 350=item I<is =E<gt> 'rw'|'ro'>
6ba6d68c 351
352The I<is> option accepts either I<rw> (for read/write) or I<ro> (for read
353only). These will create either a read/write accessor or a read-only
354accessor respectively, using the same name as the C<$name> of the attribute.
355
356If you need more control over how your accessors are named, you can use the
357I<reader>, I<writer> and I<accessor> options inherited from L<Moose::Meta::Attribute>.
358
076c81ed 359=item I<isa =E<gt> $type_name>
6ba6d68c 360
361The I<isa> option uses Moose's type constraint facilities to set up runtime
362type checking for this attribute. Moose will perform the checks during class
363construction, and within any accessors. The C<$type_name> argument must be a
364string. The string can be either a class name, or a type defined using
365Moose's type defintion features.
366
daea75c9 367=item I<coerce =E<gt> (1|0)>
368
369This will attempt to use coercion with the supplied type constraint to change
370the value passed into any accessors of constructors. You B<must> have supplied
371a type constraint in order for this to work. See L<Moose::Cookbook::Recipe5>
372for an example usage.
373
374=item I<does =E<gt> $role_name>
375
376This will accept the name of a role which the value stored in this attribute
377is expected to have consumed.
378
379=item I<required =E<gt> (1|0)>
380
381This marks the attribute as being required. This means a value must be supplied
382during class construction, and the attribute can never be set to C<undef> with
383an accessor.
384
385=item I<weak_ref =E<gt> (1|0)>
386
387This will tell the class to strore the value of this attribute as a weakened
388reference. If an attribute is a weakened reference, it can B<not> also be coerced.
389
390=item I<lazy =E<gt> (1|0)>
391
392This will tell the class to not create this slot until absolutely nessecary.
393If an attribute is marked as lazy it B<must> have a default supplied.
394
395=item I<trigger =E<gt> $code>
396
397The trigger option is a CODE reference which will be called after the value of
398the attribute is set. The CODE ref will be passed the instance itself, the
399updated value and the attribute meta-object (this is for more advanced fiddling
cce8198b 400and can typically be ignored in most cases). You can B<not> have a trigger on
401a read-only attribute.
daea75c9 402
6ba6d68c 403=back
404
076c81ed 405=item B<before $name|@names =E<gt> sub { ... }>
6ba6d68c 406
076c81ed 407=item B<after $name|@names =E<gt> sub { ... }>
6ba6d68c 408
076c81ed 409=item B<around $name|@names =E<gt> sub { ... }>
6ba6d68c 410
411This three items are syntactic sugar for the before, after and around method
412modifier features that L<Class::MOP> provides. More information on these can
413be found in the L<Class::MOP> documentation for now.
414
159da176 415=item B<super>
416
417The keyword C<super> is a noop when called outside of an C<override> method. In
418the context of an C<override> method, it will call the next most appropriate
419superclass method with the same arguments as the original method.
420
421=item B<override ($name, &sub)>
422
423An C<override> method, is a way of explictly saying "I am overriding this
424method from my superclass". You can call C<super> within this method, and
425it will work as expected. The same thing I<can> be accomplished with a normal
426method call and the C<SUPER::> pseudo-package, it is really your choice.
427
428=item B<inner>
429
430The keyword C<inner>, much like C<super>, is a no-op outside of the context of
431an C<augment> method. You can think of C<inner> as being the inverse of
432C<super>, the details of how C<inner> and C<augment> work is best described in
433the L<Moose::Cookbook>.
434
435=item B<augment ($name, &sub)>
436
437An C<augment> method, is a way of explictly saying "I am augmenting this
438method from my superclass". Once again, the details of how C<inner> and
439C<augment> work is best described in the L<Moose::Cookbook>.
440
6ba6d68c 441=item B<confess>
442
443This is the C<Carp::confess> function, and exported here beause I use it
444all the time. This feature may change in the future, so you have been warned.
445
446=item B<blessed>
447
448This is the C<Scalar::Uti::blessed> function, it is exported here beause I
449use it all the time. It is highly recommended that this is used instead of
450C<ref> anywhere you need to test for an object's class name.
451
452=back
453
05d9eaf6 454=head1 CAVEATS
455
456=over 4
457
458=item *
459
460It should be noted that C<super> and C<inner> can B<not> be used in the same
461method. However, they can be combined together with the same class hierarchy,
462see F<t/014_override_augment_inner_super.t> for an example.
463
464The reason that this is so is because C<super> is only valid within a method
465with the C<override> modifier, and C<inner> will never be valid within an
466C<override> method. In fact, C<augment> will skip over any C<override> methods
467when searching for it's appropriate C<inner>.
468
469This might seem like a restriction, but I am of the opinion that keeping these
470two features seperate (but interoperable) actually makes them easy to use since
471their behavior is then easier to predict. Time will tell if I am right or not.
472
473=back
474
5569c072 475=head1 ACKNOWLEDGEMENTS
476
477=over 4
478
54c189df 479=item I blame Sam Vilain for introducing me to the insanity that is meta-models.
5569c072 480
54c189df 481=item I blame Audrey Tang for then encouraging my meta-model habit in #perl6.
5569c072 482
076c81ed 483=item Without Yuval "nothingmuch" Kogman this module would not be possible,
54c189df 484and it certainly wouldn't have this name ;P
5569c072 485
486=item The basis of the TypeContraints module was Rob Kinyon's idea
487originally, I just ran with it.
488
076c81ed 489=item Thanks to mst & chansen and the whole #moose poose for all the
d46a48f3 490ideas/feature-requests/encouragement
491
5569c072 492=back
493
e90c03d0 494=head1 SEE ALSO
495
496=over 4
497
6ba6d68c 498=item L<Class::MOP> documentation
499
500=item The #moose channel on irc.perl.org
501
e90c03d0 502=item L<http://forum2.org/moose/>
503
159da176 504=item L<http://www.cs.utah.edu/plt/publications/oopsla04-gff.pdf>
505
506This paper (suggested by lbr on #moose) was what lead to the implementation
507of the C<super>/C<overrride> and C<inner>/C<augment> features. If you really
508want to understand this feature, I suggest you read this.
509
e90c03d0 510=back
511
fcd84ca9 512=head1 BUGS
513
514All complex software has bugs lurking in it, and this module is no
515exception. If you find a bug please either email me, or add the bug
516to cpan-RT.
517
fcd84ca9 518=head1 AUTHOR
519
520Stevan Little E<lt>stevan@iinteractive.comE<gt>
521
522=head1 COPYRIGHT AND LICENSE
523
524Copyright 2006 by Infinity Interactive, Inc.
525
526L<http://www.iinteractive.com>
527
528This library is free software; you can redistribute it and/or modify
529it under the same terms as Perl itself.
530
ddd0ec20 531=cut