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