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